1 Star 0 Fork 0

Bin/kir

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
result.go 6.60 KB
一键复制 编辑 原始数据 按行查看 历史
bin you 提交于 2024-09-22 00:02 . op
package main
import (
"encoding/binary"
"fmt"
"math"
)
type ColumnDefinition struct {
Schema string
Table string
OrgTable string
Name string
OrgName string
CharacterSet uint16
ColumnLength uint32
ColumnType byte
Flags uint16
Decimals byte
}
func (mr *monitoredConnection) handleFieldPacket(packet []byte) {
field, err := parseFieldPacket(packet)
if err != nil {
// fmt.Println("解析字段定义包失败:", err)
return
}
mr.currentResult.Columns = append(mr.currentResult.Columns, field)
}
func (mr *monitoredConnection) handleRowPacket(packet []byte) {
if mr.currentState != 1 {
return
}
row, err := parseRowPacket(packet, mr.currentResult.Columns)
if err != nil {
fmt.Println("解析数据行包失败:", err)
return
}
mr.currentResult.Rows = append(mr.currentResult.Rows, row)
}
func (mr *monitoredConnection) handleEOFOrOKPacket(packet []byte) {
if len(packet) < 5 {
fmt.Println("无效的EOF或OK包")
return
}
// 检查是否为OK包(MySQL 5.7.5及更高版本可能会发送OK包而不是EOF包)
isOK := packet[0] == 0x00 && len(packet) >= 7
// 检查是否为EOF包
isEOF := packet[0] == 0xfe && len(packet) < 9
if isOK {
// 处理OK包
mr.handleOKPacket(packet)
} else if isEOF {
// 处理EOF包
mr.handleEOFPacket(packet)
} else {
fmt.Println("未知的包类型")
}
}
func (mr *monitoredConnection) handleOKPacket(packet []byte) {
// 处理OK包逻辑
affectedRows := packet[1]
lastInsertID := packet[2]
mr.currentResult.AffectedRows = int64(affectedRows)
mr.currentResult.LastInsertID = int64(lastInsertID)
mr.addSqlResult()
// mr.currentSQL = ""
}
func (mr *monitoredConnection) handleEOFPacket(packet []byte) {
// 处理EOF包逻辑3
statusFlags := binary.LittleEndian.Uint16(packet[3:5])
if statusFlags&0x0008 == 0 {
if mr.currentState == 0 {
mr.currentState = 1
} else if mr.currentState == 1 {
mr.addSqlResult()
}
// SERVER_MORE_RESULTS_EXISTS 标志未设置,表示结果集传输完成
// mr.addSqlResult()
// mr.currentSQL = ""
}
}
func parseFieldPacket(packet []byte) (ColumnDefinition, error) {
var field ColumnDefinition
var pos int
field.Schema, pos = getLengthEncodedString(packet, 0)
field.Table, pos = getLengthEncodedString(packet, pos)
field.OrgTable, pos = getLengthEncodedString(packet, pos)
field.Name, pos = getLengthEncodedString(packet, pos)
field.OrgName, pos = getLengthEncodedString(packet, pos)
if len(packet) < pos+13 {
return field, fmt.Errorf("字段定义包数据不足")
}
pos++ // 跳过0x0C
field.CharacterSet = binary.LittleEndian.Uint16(packet[pos:])
pos += 2
field.ColumnLength = binary.LittleEndian.Uint32(packet[pos:])
pos += 4
field.ColumnType = packet[pos]
pos++
field.Flags = binary.LittleEndian.Uint16(packet[pos:])
pos += 2
field.Decimals = packet[pos]
return field, nil
}
func parseRowPacket(packet []byte, columns []ColumnDefinition) ([]interface{}, error) {
var row []interface{}
pos := 0
for _, col := range columns {
if pos >= len(packet) {
return nil, fmt.Errorf("数据包长度不足")
}
if packet[pos] == 0xfb {
row = append(row, nil)
pos++
continue
}
value, bytesRead, err := parseMySQLValue(packet[pos:], col)
if err != nil {
return nil, err
}
row = append(row, value)
pos += bytesRead
}
return row, nil
}
func parseMySQLValue(data []byte, col ColumnDefinition) (interface{}, int, error) {
length, numBytes := getLengthEncodedInteger(data)
if numBytes == 0 {
return nil, 0, fmt.Errorf("无效的长度编码整数")
}
if int(length)+numBytes > len(data) {
return nil, 0, fmt.Errorf("数据包长度不足")
}
value := data[numBytes : numBytes+int(length)]
switch col.ColumnType {
case 0x01, 0x02, 0x03, 0x08: // TINY, SHORT, LONG, LONGLONG
return parseIntegerValue(value, col.ColumnType)
case 0x04, 0x05: // FLOAT, DOUBLE
return parseFloatValue(value, col.ColumnType)
case 0x0f, 0xfe: // VARCHAR, STRING
return string(value), numBytes + int(length), nil
// 可以根据需要添加更多类型的处理
default:
return string(value), numBytes + int(length), nil
}
}
func parseIntegerValue(data []byte, columnType byte) (interface{}, int, error) {
switch columnType {
case 0x01: // TINY
return int8(data[0]), 1, nil
case 0x02: // SHORT
return int16(binary.LittleEndian.Uint16(data)), 2, nil
case 0x03: // LONG
return int32(binary.LittleEndian.Uint32(data)), 4, nil
case 0x08: // LONGLONG
return int64(binary.LittleEndian.Uint64(data)), 8, nil
default:
return nil, 0, fmt.Errorf("未知的整数类型")
}
}
func parseFloatValue(data []byte, columnType byte) (interface{}, int, error) {
switch columnType {
case 0x04: // FLOAT
bits := binary.LittleEndian.Uint32(data)
return math.Float32frombits(bits), 4, nil
case 0x05: // DOUBLE
bits := binary.LittleEndian.Uint64(data)
return math.Float64frombits(bits), 8, nil
default:
return nil, 0, fmt.Errorf("未知的浮点类型")
}
}
func getLengthEncodedInteger(data []byte) (uint64, int) {
if len(data) == 0 {
return 0, 0
}
switch data[0] {
case 0xfc:
if len(data) < 3 {
return 0, 0
}
return uint64(data[1]) | uint64(data[2])<<8, 3
case 0xfd:
if len(data) < 4 {
return 0, 0
}
return uint64(data[1]) | uint64(data[2])<<8 | uint64(data[3])<<16, 4
case 0xfe:
if len(data) < 9 {
return 0, 0
}
return binary.LittleEndian.Uint64(data[1:]), 9
default:
return uint64(data[0]), 1
}
}
func getLengthEncodedString(data []byte, start int) (string, int) {
length, numBytes := getLengthEncodedInteger(data[start:])
if numBytes == 0 {
return "", start
}
end := start + numBytes + int(length)
if end > len(data) {
return "", start
}
return string(data[start+numBytes : end]), end
}
func getColumnTypeName(columnType byte) string {
switch columnType {
case 0x00:
return "DECIMAL"
case 0x01:
return "TINY"
case 0x02:
return "SHORT"
case 0x03:
return "LONG"
case 0x04:
return "FLOAT"
case 0x05:
return "DOUBLE"
case 0x06:
return "NULL"
case 0x07:
return "TIMESTAMP"
case 0x08:
return "LONGLONG"
case 0x09:
return "INT24"
case 0x0a:
return "DATE"
case 0x0b:
return "TIME"
case 0x0c:
return "DATETIME"
case 0x0d:
return "YEAR"
case 0x0e:
return "NEWDATE"
case 0x0f:
return "VARCHAR"
case 0x10:
return "BIT"
case 0xf6:
return "NEWDECIMAL"
case 0xf7:
return "ENUM"
case 0xf8:
return "SET"
case 0xf9:
return "TINY_BLOB"
case 0xfa:
return "MEDIUM_BLOB"
case 0xfb:
return "LONG_BLOB"
case 0xfc:
return "BLOB"
case 0xfd:
return "VAR_STRING"
case 0xfe:
return "STRING"
case 0xff:
return "GEOMETRY"
default:
return fmt.Sprintf("UNKNOWN(%d)", columnType)
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/llyb120/kir.git
[email protected]:llyb120/kir.git
llyb120
kir
kir
master

搜索帮助