package xugu import ( "database/sql/driver" "encoding/binary" "errors" "fmt" "strconv" "strings" "time" ) type ParseParam interface { // 转换参数数据类型 assertParamType(driver.Value, int) error // 解析参数数量 assertParamCount(string) int // 解析参数绑定类型(按参数名称绑定类型和按参数位置绑定类型) assertBindType(string) int // 解析参数名称 assertParamName(string) error } // 辅助结构体 type xuguValue struct { // 布尔值,如果值为 true,表示当前字段的数据类型是大对象数据类型 islob bool plob []byte //字段名 paramName []byte //paramNameLength [2]byte // 字段的实际值 value []byte // 值的长度 valueLength int // buff 通常指定要绑定的参数数据的内存缓冲区大小 //buff 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: // re := cgo_xgc_new_lob(&dest.plob) // if re < 0 { // return errors.New("Cannot create new large object") // } srcv, ok := dV.([]byte) if !ok { return errors.New("assertParamType []byte error") } // cgo_xgc_put_lob_data( // &dest.plob, // unsafe.Pointer((*C.char)(unsafe.Pointer(&srcv[0]))), // len(srcv)) // cgo_xgc_put_lob_data(&dest.plob, nil, -1) 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.position = pos 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 } 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_I4, fieldType_I8: 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++ } //swich end fmt.Println("循环结束") return data, nil } //for end } else { break } default: return nil, errors.New("parseQueryResult error") } //swich end 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 }