package xugu import ( "database/sql/driver" "encoding/binary" "errors" "fmt" "strconv" "strings" "time" ) // 辅助结构体 type xuguValue struct { // 布尔值,如果值为 true,表示当前字段的数据类型是大对象数据类型 islob bool //字段名 paramName []byte //paramNameLength [2]byte // 字段的实际值 value []byte // 值的长度 valueLength int // 字段的类型 types fieldType } type xuguParse struct { // bind_type 用于标识参数绑定的类型。 // 参数绑定类型包括按参数名称绑定和按参数占位符绑定 bind_type int // param_count 用于指定在 SQL 语句中需要绑定的参数数量 param_count int // 当参数绑定类型为按参数名称绑定时,param_names 是参数名称的集合 param_names []byte values []xuguValue // 当参数绑定类型为按参数占位符绑定时,position 标识参数的位置 //position int } // 判断参数个数 func (Parse *xuguParse) assertParamCount(query string) int { fmt.Println("----assertParamCount func 判断参数个数") if Parse.bind_type == 0 { Parse.bind_type = Parse.assertBindType(query) } switch Parse.bind_type { case BIND_PARAM_BY_POS: Parse.param_count = strings.Count(query, "?") fmt.Println("Parse.param_count ", Parse.param_count) case BIND_PARAM_BY_NAME: Parse.param_count = 0 pos := 0 phead := -1 for { pos = strings.IndexByte(query[phead+1:], ':') if pos == -1 { break } pos += phead + 1 tmp := pos for tmp > phead { tmp-- if query[tmp] == ' ' { continue } if query[tmp] == ',' || query[tmp] == '(' { Parse.param_count++ } break } phead = pos } } return Parse.param_count } // 判断绑定类型 ? 或者 :name func (Parse *xuguParse) assertBindType(query string) int { fmt.Println("--assertBindType") Parse.bind_type = strings.IndexByte(query, '?') fmt.Println("Parse.bind_type", Parse.bind_type) if Parse.bind_type != -1 { Parse.bind_type = BIND_PARAM_BY_POS return BIND_PARAM_BY_POS } Parse.bind_type = BIND_PARAM_BY_NAME return BIND_PARAM_BY_NAME } // 判断参数变量类型 func (param *xuguParse) assertParamType(dV driver.Value, pos int) error { fmt.Println("-----(param *xuguParse) assertParamType 判断参数类型") var dest xuguValue switch dV.(type) { case int64: srcv, ok := dV.(int64) if !ok { return errors.New("assertParamType int64 error") } S := strconv.FormatInt(srcv, 10) dest.value = []byte(S) dest.valueLength = strings.Count(S, "") - 1 dest.islob = false dest.types = fieldType_I8 case float32: srcv, ok := dV.(float64) if !ok { return errors.New("assertParamType float32 error") } S := strconv.FormatFloat(srcv, 'f', 6, 64) dest.value = []byte(S) dest.valueLength = strings.Count(S, "") - 1 dest.islob = false dest.types = fieldType_R4 case float64: srcv, ok := dV.(float64) if !ok { return errors.New("assertParamType float64 error") } S := strconv.FormatFloat(srcv, 'f', 15, 64) dest.value = []byte(S) dest.valueLength = strings.Count(S, "") - 1 dest.islob = false dest.types = fieldType_R8 case bool: srcv, ok := dV.(bool) if !ok { return errors.New("assertParamType bool error") } S := strconv.FormatBool(srcv) dest.value = []byte(S) dest.valueLength = strings.Count(S, "") - 1 dest.islob = false dest.types = fieldType_BOOL case string: S, ok := dV.(string) if !ok { return errors.New("assertParamType string error") } fmt.Println("是string") dest.value = []byte(S) dest.valueLength = strings.Count(S, "") - 1 dest.islob = false dest.types = fieldType_CHAR fmt.Printf("是string类型: %#v\n", dest) case time.Time: srcv, ok := dV.(time.Time) if !ok { return errors.New("assertParamType time error") } tm := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", srcv.Year(), int(srcv.Month()), srcv.Day(), srcv.Hour(), srcv.Minute(), srcv.Second()) dest.value = []byte(tm) dest.valueLength = strings.Count(tm, "") - 1 dest.islob = false dest.types = fieldType_TIME case []byte: srcv, ok := dV.([]byte) if !ok { return errors.New("assertParamType []byte error") } dest.value = srcv dest.valueLength = len(srcv) dest.islob = true dest.types = fieldType_BLOB fmt.Println("-----判断参数类型为 byte[]") case nil: dest.value = []byte("xugusql") dest.valueLength = 0 dest.islob = false dest.types = fieldType_CHAR default: /* OTHER DATA TYPE */ return errors.New("Unknown data type") } param.values = append(param.values, dest) return nil } // 判断参数名 func (param *xuguParse) assertParamName(query string) error { fmt.Println("----(param *xuguParse) assertParamName 判断参数名") if param.param_count <= 0 { param.assertParamCount(query) } pos := 0 phead := -1 for { pos = strings.IndexByte(query[phead+1:], ':') if pos == -1 { break } pos += phead + 1 tmp := pos for tmp > phead { tmp-- if query[tmp] == ' ' { continue } // Parse parameter positions bound by parameter name if query[tmp] == ',' || query[tmp] == '(' { parg := pos for true { parg++ if query[parg] == ',' || query[parg] == ')' || query[parg] == ' ' { param.param_names = append(param.param_names, query[pos+1:parg]...) break } } } break } phead = pos } fmt.Printf("param: %#v", param) fmt.Printf("param: %#v", query) fmt.Println("----(param *xuguParse) assertParamName 判断参数名结束") return nil } func (param *xuguParse) bindParamByPos(query string) string { fmt.Println("----(param *xuguParse) bindParamByPos ") fmt.Printf("param: %#v \n", param) for i := 0; i < param.param_count; i++ { //sql语句里替换夫的下标, 替换为 query = strings.Replace(query, "?", string(param.values[i].value), 1) } return query } type SelectResult struct { Field_Num uint32 Fields []FieldDescri Values [][]ValueData //[字段][字段所有值] rowIdx int } type FieldDescri struct { FieldNameLen int FieldName string FieldType fieldType FieldPreciScale int FieldFlag int } type ValueData struct { Col_len uint32 Col_Data []byte } type InsertResult struct { RowidLen uint32 RowidData []byte } type UpdateResult struct { UpdateNum uint32 } type DeleteResult struct { DeleteNum uint32 } type ProcRet struct { RetDType uint32 RetDataLen uint32 RetData []byte } type OutParamRet struct { OutParamNo uint32 OutParamDType uint32 OutParamLen uint32 OutParamData []byte } type ErrInfo struct { ErrStrLen uint32 ErrStr []byte } type WarnInfo struct { WarnStrLen uint32 WarnStr []byte } type Message struct { MsgStrLen uint32 MsgStr []byte } type FormArgDescri struct { ArgNum uint32 Args []ArgDescri } type ArgDescri struct { ArgNameLen uint32 ArgName []byte ArgNo uint32 ArgDType uint32 ArgPreciScale uint32 } type allResult struct { rt msgType s *SelectResult i *InsertResult u *UpdateResult d *DeleteResult p *ProcRet o *OutParamRet e *ErrInfo w *WarnInfo m *Message f *FormArgDescri } func parseSelectResult(readBuf *buffer) (*SelectResult, error) { fmt.Println("调用 parseSelectResult") data := &SelectResult{} char := readBuf.peekChar() fmt.Println("--=char: ", string(char)) switch char { case 'A': readBuf.idx++ //Field_Num Field_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) data.Field_Num = Field_Num data.rowIdx = 0 fmt.Println("Field_Num: ", data.Field_Num) //获取字段信息 for i := 0; i < int(Field_Num); i++ { field := FieldDescri{} //Field_Name_Len field.FieldNameLen = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true))) fmt.Println("field.FieldNameLen: ", field.FieldNameLen) //Field_Name: field.FieldName = string(readBuf.readNext(field.FieldNameLen, false)) fmt.Println("field.Field_Name: ", field.FieldName) //Field_DType: field.FieldType = fieldType(binary.LittleEndian.Uint32(readBuf.readNext(4, true))) fmt.Println("field.FieldType: ", field.FieldType) //Field_Preci_Scale: field.FieldPreciScale = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true))) fmt.Println("field.FieldPreciScale: ", field.FieldPreciScale) //Field_Flag: field.FieldFlag = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true))) fmt.Println("field.FieldFlag: ", field.FieldFlag) data.Fields = append(data.Fields, field) } data.Values = make([][]ValueData, data.Field_Num) //获取字段的行值,并判断类型 // 使用 Peek 方法检查下一个字节是否为'R'或'K' fmt.Println("\n\n=========开始获取行数据=================================") defer func() { fmt.Println("\n\n=========获取行数据结束=================================") }() char := readBuf.peekChar() fmt.Println(" --char: ", string(char)) readBuf.idx++ if char == 'K' { break } else if char == 'R' { colIdx := 0 typeIdx := 0 fmt.Println("开始循环 ") for { col := ValueData{} //获取数据的大小 col.Col_len = binary.LittleEndian.Uint32(readBuf.readNext(4, true)) fmt.Println("数据大小为: ", col.Col_len) //获取数据 //判断类型 fmt.Println("查看类型", data.Fields[typeIdx].FieldType) switch data.Fields[typeIdx].FieldType { case fieldType_CHAR, fieldType_NCHAR: col.Col_Data = readBuf.readNext(int(col.Col_len), false) fmt.Println("fieldTypeVarChar data: ", col.Col_Data, string(col.Col_Data)) data.Values[colIdx] = append(data.Values[colIdx], col) colIdx++ fmt.Println("从查询返回 解析出的值 :", col.Col_Data, string(col.Col_Data)) char := readBuf.peekChar() if char == 'R' { readBuf.idx++ colIdx = 0 if typeIdx >= int(data.Field_Num)-1 { typeIdx = 0 } else { typeIdx++ } continue } else if char == 'K' { return data, nil //break } typeIdx++ //fieldTypeTinyint, case fieldType_I1, fieldType_I2, fieldType_I4, fieldType_I8, fieldType_R4, fieldType_R8, fieldType_DATE, fieldType_TIME, fieldType_DATETIME, fieldType_TIME_TZ: col.Col_Data = reverseBytes(readBuf.readNext(int(col.Col_len), false)) data.Values[colIdx] = append(data.Values[colIdx], col) colIdx++ char := readBuf.peekChar() fmt.Println("从查询返回 解析出的值 :", col.Col_Data, string(col.Col_Data)) if char == 'R' { readBuf.idx++ colIdx = 0 if typeIdx >= int(data.Field_Num)-1 { fmt.Println("typeIdx <= int(data.Field_Num)-1: ", typeIdx, int(data.Field_Num)-1) typeIdx = 0 } else { typeIdx++ } continue } else if char == 'K' { return data, nil //break } typeIdx++ case fieldType_CLOB, fieldType_BLOB, fieldType_BINARY: col.Col_Data = readBuf.readNext(int(col.Col_len), false) data.Values[colIdx] = append(data.Values[colIdx], col) colIdx++ char := readBuf.peekChar() fmt.Println("从查询返回 解析出的值 :", col.Col_Data, string(col.Col_Data)) if char == 'R' { readBuf.idx++ colIdx = 0 if typeIdx >= int(data.Field_Num)-1 { fmt.Println("typeIdx <= int(data.Field_Num)-1: ", typeIdx, int(data.Field_Num)-1) typeIdx = 0 } else { typeIdx++ } continue } else if char == 'K' { return data, nil //break } } //swich end fmt.Println("循环结束") fmt.Printf("解析请求 data:%#v\n", data.Fields) return data, nil } //for end } else { break } default: fmt.Println("解析请求 错误", data.Fields) return nil, errors.New("parseQueryResult error") } //swich end fmt.Println("解析请求 data", data.Fields) return data, nil } func parseInsertResult(readBuf *buffer) (*InsertResult, error) { //Rowid_Len Rowid_Len := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) //Rowid_Data encoded := readBuf.readNext(int(Rowid_Len), false) //检测是否结束 char := readBuf.peekChar() if char == 'K' { return &InsertResult{ RowidLen: Rowid_Len, RowidData: encoded, }, nil } return nil, errors.New("parseInsertResult error") } func parseUpdateResult(readBuf *buffer) (*UpdateResult, error) { updateNum := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) return &UpdateResult{UpdateNum: updateNum}, nil } func parseDeleteResult(readBuf *buffer) (*DeleteResult, error) { deleteNum := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) return &DeleteResult{DeleteNum: deleteNum}, nil } func parseProcRet(readBuf *buffer) (*ProcRet, error) { retDType := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) retDataLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) retData := readBuf.readNext(int(retDataLen), false) return &ProcRet{RetDType: retDType, RetDataLen: retDataLen, RetData: retData}, nil } func parseOutParamRet(readBuf *buffer) (*OutParamRet, error) { outParamNo := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) outParamDType := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) outParamLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) outParamData := readBuf.readNext(int(outParamLen), false) return &OutParamRet{ OutParamNo: outParamNo, OutParamDType: outParamDType, OutParamLen: outParamLen, OutParamData: outParamData, }, nil } func parseErrInfo(readBuf *buffer) (*ErrInfo, error) { errStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) errStr := readBuf.readNext(int(errStrLen), false) return &ErrInfo{ErrStrLen: errStrLen, ErrStr: errStr}, nil } func parseWarnInfo(readBuf *buffer) (*WarnInfo, error) { warnStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) warnStr := readBuf.readNext(int(warnStrLen), false) return &WarnInfo{WarnStrLen: warnStrLen, WarnStr: warnStr}, nil } func parseMessage(readBuf *buffer) (*Message, error) { msgStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) msgStr := readBuf.readNext(int(msgStrLen), false) return &Message{MsgStrLen: msgStrLen, MsgStr: msgStr}, nil } func parseFormArgDescri(readBuf *buffer) (*FormArgDescri, error) { // FormArgDescri: '$' Arg_Num { Arg_Name_Len Arg_Name Arg_No Arg_DType Arg_Preci_Scale }+ Arg_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true)) formArgDescri := &FormArgDescri{ArgNum: Arg_Num} fmt.Println("-- parseFormArgDescri Arg_Num:", Arg_Num) for i := 0; i < int(Arg_Num); i++ { arg := ArgDescri{} //Arg_Name_Len arg.ArgNameLen = binary.LittleEndian.Uint32(readBuf.readNext(4, true)) //Arg_Name arg.ArgName = readBuf.readNext(int(arg.ArgNameLen), false) //Arg_No arg.ArgNo = binary.LittleEndian.Uint32(readBuf.readNext(4, true)) //Argg_DType arg.ArgDType = binary.LittleEndian.Uint32(readBuf.readNext(4, true)) //Arg_Preci_Scale arg.ArgPreciScale = binary.LittleEndian.Uint32(readBuf.readNext(4, true)) formArgDescri.Args = append(formArgDescri.Args, arg) } fmt.Printf("formArgDescri %#v \n", formArgDescri) return formArgDescri, nil } func parseMsg(readBuf *buffer, pConn *xuguConn) (*allResult, error) { var err error aR := allResult{} for { char := readBuf.peekChar() fmt.Println("parseMsg 内的 peekChar: ", char, "-", string(char)) switch char { case 'K': fmt.Println("消息类型为K") // readBuf.buf = make([]byte, 2048) //readBuf.idx++ // readBuf.buf = make([]byte, 2048) // readBuf.idx = 0 readBuf.reset() return &aR, nil case '$': readBuf.idx++ fmt.Println("消息类型为$") if aR.f, err = parseFormArgDescri(readBuf); err != nil { return nil, err } aR.rt = '$' return &aR, err case 'A': //readBuf.idx++ fmt.Println("消息类型为A") if aR.s, err = parseSelectResult(readBuf); err != nil { return nil, err } aR.rt = 'A' return &aR, err case 'I': readBuf.idx++ fmt.Println("消息类型为I") if aR.i, err = parseInsertResult(readBuf); err != nil { return nil, err } aR.rt = 'I' return &aR, err case 'U': fmt.Println("消息类型为U") readBuf.idx++ if aR.u, err = parseUpdateResult(readBuf); err != nil { return nil, err } aR.rt = 'U' return &aR, err case 'D': fmt.Println("消息类型为D") readBuf.idx++ readBuf.idx++ if aR.d, err = parseDeleteResult(readBuf); err != nil { return nil, err } aR.rt = 'D' return &aR, err case 'E': fmt.Println("消息类型为E") readBuf.idx++ if aR.e, err = parseErrInfo(readBuf); err != nil { return nil, err } pConn.errStr = aR.e.ErrStr aR.rt = 'E' return &aR, err case 'W': fmt.Println("消息类型为W") readBuf.idx++ if aR.w, err = parseWarnInfo(readBuf); err != nil { return nil, err } aR.rt = 'W' return &aR, err case 'M': fmt.Println("消息类型为M") readBuf.idx++ if aR.m, err = parseMessage(readBuf); err != nil { return nil, err } aR.rt = 'M' return &aR, err default: fmt.Println("消息类型为其他") return nil, errors.New("parseMsg: unknown message type") } } } // func handleParsedMsg(params ParseMsgParams) (ParseResult, error) { // result, err := parseMsg(params) // if err != nil { // return nil, err // } // result.Process() // return result, nil // }