From 16c99331a9e2bf5df465f7236bee9975b5396900 Mon Sep 17 00:00:00 2001 From: Garet Halliday <me@garet.holiday> Date: Fri, 25 Aug 2023 12:34:57 -0500 Subject: [PATCH] unmarshal --- lib/psql/query.go | 12 ++++- lib/psql/query_test.go | 2 +- lib/zap/packets/v3.0/datarow.go | 52 +++++++++++++++++++++ lib/zap/packets/v3.0/rowdescription.go | 63 ++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 lib/zap/packets/v3.0/datarow.go create mode 100644 lib/zap/packets/v3.0/rowdescription.go diff --git a/lib/psql/query.go b/lib/psql/query.go index c7614236..1abc8595 100644 --- a/lib/psql/query.go +++ b/lib/psql/query.go @@ -36,9 +36,17 @@ func (T *resultReader) WriteByte(_ byte) error { func (T *resultReader) WritePacket(packet zap.Packet) error { switch packet.Type() { case packets.TypeRowDescription: - log.Println("row description", packet) + var rd packets.RowDescription + if !rd.ReadFromPacket(packet) { + return errors.New("invalid format") + } + log.Printf("row description: %#v", rd) case packets.TypeDataRow: - log.Println("data row", packet) + var dr packets.DataRow + if !dr.ReadFromPacket(packet) { + return errors.New("invalid format") + } + log.Printf("data row: %#v", dr) } return nil } diff --git a/lib/psql/query_test.go b/lib/psql/query_test.go index 2f3449ee..4a573c25 100644 --- a/lib/psql/query_test.go +++ b/lib/psql/query_test.go @@ -29,7 +29,7 @@ func TestQuery(t *testing.T) { return } - err = Query(server, "SELECT * FROM pg_shadow") + err = Query(server, "SELECT usename, passwd FROM pg_shadow WHERE usename='postgres'") if err != nil { t.Error(err) return diff --git a/lib/zap/packets/v3.0/datarow.go b/lib/zap/packets/v3.0/datarow.go new file mode 100644 index 00000000..689d350e --- /dev/null +++ b/lib/zap/packets/v3.0/datarow.go @@ -0,0 +1,52 @@ +package packets + +import ( + "pggat2/lib/util/slices" + "pggat2/lib/zap" +) + +type DataRow struct { + Columns [][]byte +} + +func (T *DataRow) ReadFromPacket(packet zap.Packet) bool { + if packet.Type() != TypeDataRow { + return false + } + + var columnCount uint16 + p := packet.ReadUint16(&columnCount) + T.Columns = slices.Resize(T.Columns, int(columnCount)) + for i := 0; i < int(columnCount); i++ { + var valueLength int32 + p = p.ReadInt32(&valueLength) + if valueLength == -1 { + continue + } + T.Columns[i] = slices.Resize(T.Columns[i], int(valueLength)) + p = p.ReadBytes(T.Columns[i]) + } + + return true +} + +func (T *DataRow) IntoPacket() zap.Packet { + size := 2 + for _, v := range T.Columns { + size += len(v) + 4 + } + + packet := zap.NewPacket(TypeDataRow, size) + packet = packet.AppendUint16(uint16(len(T.Columns))) + for _, v := range T.Columns { + if v == nil { + packet = packet.AppendInt32(-1) + continue + } + + packet = packet.AppendInt32(int32(len(v))) + packet = packet.AppendBytes(v) + } + + return packet +} diff --git a/lib/zap/packets/v3.0/rowdescription.go b/lib/zap/packets/v3.0/rowdescription.go new file mode 100644 index 00000000..3febb34c --- /dev/null +++ b/lib/zap/packets/v3.0/rowdescription.go @@ -0,0 +1,63 @@ +package packets + +import ( + "pggat2/lib/util/slices" + "pggat2/lib/zap" +) + +type RowDescriptionField struct { + Name string + TableID int32 + ColumnID int16 + Type int32 + TypeLength int16 + TypeModifier int32 + FormatCode int16 +} + +type RowDescription struct { + Fields []RowDescriptionField +} + +func (T *RowDescription) ReadFromPacket(packet zap.Packet) bool { + if packet.Type() != TypeRowDescription { + return false + } + + var fieldsPerRow uint16 + p := packet.ReadUint16(&fieldsPerRow) + T.Fields = slices.Resize(T.Fields, int(fieldsPerRow)) + for i := 0; i < int(fieldsPerRow); i++ { + p = p.ReadString(&T.Fields[i].Name) + p = p.ReadInt32(&T.Fields[i].TableID) + p = p.ReadInt16(&T.Fields[i].ColumnID) + p = p.ReadInt32(&T.Fields[i].Type) + p = p.ReadInt16(&T.Fields[i].TypeLength) + p = p.ReadInt32(&T.Fields[i].TypeModifier) + p = p.ReadInt16(&T.Fields[i].FormatCode) + } + + return true +} + +func (T *RowDescription) IntoPacket() zap.Packet { + size := 2 + for _, v := range T.Fields { + size += len(v.Name) + 1 + size += 4 + 2 + 4 + 2 + 4 + 2 + } + + packet := zap.NewPacket(TypeRowDescription, size) + packet = packet.AppendUint16(uint16(len(T.Fields))) + for _, v := range T.Fields { + packet = packet.AppendString(v.Name) + packet = packet.AppendInt32(v.TableID) + packet = packet.AppendInt16(v.ColumnID) + packet = packet.AppendInt32(v.Type) + packet = packet.AppendInt16(v.TypeLength) + packet = packet.AppendInt32(v.TypeModifier) + packet = packet.AppendInt16(v.FormatCode) + } + + return packet +} -- GitLab