package mysqlserver import ( "mysql-tunnel/internal/navicat" ) func encodeColumnCount(n int) []byte { return appendLenencInt(nil, uint64(n)) } func encodeColumn(f navicat.Field) []byte { typ := byte(f.Type) charset := uint16(charsetUTF8MB4) if isNumericType(typ) || f.Flags&uint32(flagBinary) != 0 && isBlobType(typ) { charset = uint16(charsetBinary) } if isNumericType(typ) { charset = uint16(charsetBinary) } length := f.Length if length == 0 { length = uint32(len(f.Name)) if length == 0 { length = 64 } } flags := uint16(f.Flags) decimals := byte(0) if typ == typeFloat || typ == typeDouble || typ == typeNewDecimal || typ == typeDecimal { decimals = 31 } b := appendLenencString(nil, []byte("def")) b = appendLenencString(b, nil) // schema b = appendLenencString(b, []byte(f.Table)) b = appendLenencString(b, []byte(f.Table)) b = appendLenencString(b, []byte(f.Name)) b = appendLenencString(b, []byte(f.Name)) b = appendLenencInt(b, 0x0c) b = appendU16(b, charset) b = appendU32(b, length) b = append(b, typ) b = appendU16(b, flags) b = append(b, decimals, 0x00, 0x00) return b } func encodeTextRow(row []navicat.Cell) []byte { var b []byte for _, c := range row { if c.Null { b = append(b, markerNull) continue } b = appendLenencString(b, c.Bytes) } return b } func isBlobType(t byte) bool { switch t { case typeTinyBlob, typeMediumBlob, typeLongBlob, typeBlob: return true } return false } func (p *packetConn) writeResultSet(res navicat.Result, caps uint32, status uint16) error { if err := p.writePacket(encodeColumnCount(len(res.Fields))); err != nil { return err } for _, f := range res.Fields { if err := p.writePacket(encodeColumn(f)); err != nil { return err } } if caps&clientDeprecateEOF != 0 { if err := p.writeOK(0, 0, status, 0); err != nil { return err } } else { if err := p.writePacket(encodeEOF(0, status)); err != nil { return err } } for _, row := range res.Rows { if err := p.writePacket(encodeTextRow(row)); err != nil { return err } } if caps&clientDeprecateEOF != 0 { return p.writeOK(uint64(res.AffectedRows), uint64(res.InsertID), status, 0) } return p.writePacket(encodeEOF(0, status)) }