96 lines
2.2 KiB
Go
96 lines
2.2 KiB
Go
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))
|
|
}
|