|
@@ -1,9 +1,12 @@
|
|
|
package xugu
|
|
|
|
|
|
import (
|
|
|
+ "bufio"
|
|
|
"database/sql/driver"
|
|
|
"encoding/binary"
|
|
|
+ "errors"
|
|
|
"fmt"
|
|
|
+ "strconv"
|
|
|
"strings"
|
|
|
)
|
|
|
|
|
@@ -22,26 +25,25 @@ type ParseParam interface {
|
|
|
}
|
|
|
|
|
|
// 辅助结构体
|
|
|
-// type xuguValue struct {
|
|
|
-// // 布尔值,如果值为 true,表示当前字段的数据类型是大对象数据类型
|
|
|
-// islob bool
|
|
|
+type xuguValue struct {
|
|
|
+ // 布尔值,如果值为 true,表示当前字段的数据类型是大对象数据类型
|
|
|
+ islob bool
|
|
|
+ plob []byte
|
|
|
|
|
|
-// // 一个 *C.char 类型的指针,通常指向要绑定的参数值的地址
|
|
|
-// value []byte
|
|
|
-// plob []byte
|
|
|
+ // 绑定参数变量的值 ? = aa
|
|
|
+ value string
|
|
|
+ // length 通常指定要绑定的参数变量值的实际长度
|
|
|
+ length int
|
|
|
|
|
|
-// // length 通常指定要绑定的参数数据的实际长度
|
|
|
-// length []int
|
|
|
+ // buff 通常指定要绑定的参数数据的内存缓冲区大小
|
|
|
+ buff int
|
|
|
|
|
|
-// // buff 通常指定要绑定的参数数据的内存缓冲区大小
|
|
|
-// buffSize int
|
|
|
+ // ?号在 sql 语句中的位置下标
|
|
|
+ types int
|
|
|
|
|
|
-// // 在参数绑定时,指定表中字段的数据类型
|
|
|
-// types int
|
|
|
-
|
|
|
-// // 返回代码
|
|
|
-// rcode int
|
|
|
-// }
|
|
|
+ // 返回代码
|
|
|
+ rcode int
|
|
|
+}
|
|
|
|
|
|
type xuguParse struct {
|
|
|
// bind_type 用于标识参数绑定的类型。
|
|
@@ -54,22 +56,21 @@ type xuguParse struct {
|
|
|
// 当参数绑定类型为按参数名称绑定时,param_names 是参数名称的集合
|
|
|
param_names []byte
|
|
|
|
|
|
- //Val []xuguValue
|
|
|
+ Val []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)
|
|
|
}
|
|
|
- fmt.Println("**Parse.bind_type is", Parse.bind_type)
|
|
|
switch Parse.bind_type {
|
|
|
case BIND_PARAM_BY_POS:
|
|
|
Parse.param_count = strings.Count(query, "?")
|
|
|
case BIND_PARAM_BY_NAME:
|
|
|
- fmt.Println(">case BIND_PARAM_BY_NAME")
|
|
|
Parse.param_count = 0
|
|
|
pos := 0
|
|
|
phead := -1
|
|
@@ -96,39 +97,38 @@ func (Parse *xuguParse) assertParamCount(query string) int {
|
|
|
phead = pos
|
|
|
}
|
|
|
}
|
|
|
- fmt.Println("**Parse.param_count", Parse.param_count)
|
|
|
return Parse.param_count
|
|
|
}
|
|
|
|
|
|
+// 判断绑定类型 ? 或者 :name
|
|
|
func (Parse *xuguParse) assertBindType(query string) int {
|
|
|
- fmt.Println("-----(param *xuguParse) assertBindType 判断绑定类型")
|
|
|
+ fmt.Println("--assertBindType")
|
|
|
Parse.bind_type = strings.IndexByte(query, '?')
|
|
|
+ fmt.Println("Parse.bind_type", Parse.bind_type)
|
|
|
if Parse.bind_type != -1 {
|
|
|
- fmt.Println("** 是大对象语句")
|
|
|
return BIND_PARAM_BY_POS
|
|
|
}
|
|
|
- fmt.Println("** 不是大对象语句")
|
|
|
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) {
|
|
|
+ var dest xuguValue
|
|
|
+ switch dV.(type) {
|
|
|
|
|
|
- // case int64:
|
|
|
- // srcv, ok := dV.(int64)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("int64")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
+ case int64:
|
|
|
+ srcv, ok := dV.(int64)
|
|
|
+ if !ok {
|
|
|
+ return errors.New("assertParamType int64 error")
|
|
|
+ }
|
|
|
|
|
|
- // S := strconv.FormatInt(srcv, 10)
|
|
|
- // dest.value = C.CString(S)
|
|
|
- // dest.length = C.int(strings.Count(S, "") - 1)
|
|
|
- // dest.buff = dest.length + 1
|
|
|
- // dest.islob = false
|
|
|
- // dest.types = SQL_XG_C_CHAR
|
|
|
+ S := strconv.FormatInt(srcv, 10)
|
|
|
+ dest.value = S
|
|
|
+ dest.length = strings.Count(S, "") - 1
|
|
|
+ dest.buff = dest.length + 1
|
|
|
+ dest.islob = false
|
|
|
+ dest.types = SQL_XG_C_CHAR
|
|
|
|
|
|
// case float32:
|
|
|
// srcv, ok := dV.(float64)
|
|
@@ -172,22 +172,22 @@ func (param *xuguParse) assertParamType(dV driver.Value, pos int) error {
|
|
|
// dest.islob = false
|
|
|
// dest.types = SQL_XG_C_CHAR
|
|
|
|
|
|
- // case string:
|
|
|
- // srcv, ok := dV.(string)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("string")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
+ case string:
|
|
|
+ srcv, ok := dV.(string)
|
|
|
+ if !ok {
|
|
|
|
|
|
- // dest.value = C.CString(srcv)
|
|
|
- // dest.length = C.int(strings.Count(srcv, "") - 1)
|
|
|
- // dest.buff = dest.length + 1
|
|
|
- // dest.islob = false
|
|
|
- // dest.types = SQL_XG_C_CHAR
|
|
|
+ return errors.New("assertParamType string error")
|
|
|
+ }
|
|
|
|
|
|
- // if dest.length == 0 {
|
|
|
- // dest.length = 1
|
|
|
- // }
|
|
|
+ dest.value = srcv
|
|
|
+ dest.length = strings.Count(srcv, "") - 1
|
|
|
+ dest.buff = dest.length + 1
|
|
|
+ dest.islob = false
|
|
|
+ dest.types = SQL_XG_C_CHAR
|
|
|
+
|
|
|
+ if dest.length == 0 {
|
|
|
+ dest.length = 1
|
|
|
+ }
|
|
|
|
|
|
// case time.Time:
|
|
|
// srcv, ok := dV.(time.Time)
|
|
@@ -232,24 +232,25 @@ func (param *xuguParse) assertParamType(dV driver.Value, pos int) error {
|
|
|
// dest.islob = true
|
|
|
// dest.types = SQL_XG_C_BLOB
|
|
|
|
|
|
- // case nil:
|
|
|
- // dest.value = C.CString("xugusql")
|
|
|
- // dest.length = 0
|
|
|
- // dest.buff = C.int(strings.Count("xugusql", ""))
|
|
|
- // dest.islob = false
|
|
|
- // dest.types = SQL_XG_C_CHAR
|
|
|
+ case nil:
|
|
|
+ dest.value = "xugusql"
|
|
|
+ dest.length = 0
|
|
|
+ dest.buff = strings.Count("xugusql", "")
|
|
|
+ dest.islob = false
|
|
|
+ dest.types = SQL_XG_C_CHAR
|
|
|
|
|
|
- // default:
|
|
|
- // /* OTHER DATA TYPE */
|
|
|
- // return errors.New("Unknown data type")
|
|
|
- // }
|
|
|
+ default:
|
|
|
+ /* OTHER DATA TYPE */
|
|
|
+ return errors.New("Unknown data type")
|
|
|
+ }
|
|
|
|
|
|
- // param.position = pos
|
|
|
- // param.Val = append(param.Val, dest)
|
|
|
+ param.position = pos
|
|
|
+ param.Val = append(param.Val, dest)
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// 判断参数名
|
|
|
func (param *xuguParse) assertParamName(query string) error {
|
|
|
fmt.Println("----(param *xuguParse) assertParamName 判断参数名")
|
|
|
if param.param_count <= 0 {
|
|
@@ -259,7 +260,7 @@ func (param *xuguParse) assertParamName(query string) error {
|
|
|
pos := 0
|
|
|
phead := -1
|
|
|
|
|
|
- for true {
|
|
|
+ for {
|
|
|
pos = strings.IndexByte(query[phead+1:], ':')
|
|
|
if pos == -1 {
|
|
|
break
|
|
@@ -289,14 +290,28 @@ func (param *xuguParse) assertParamName(query string) error {
|
|
|
|
|
|
phead = pos
|
|
|
}
|
|
|
-
|
|
|
+ fmt.Printf("param: %#v", param)
|
|
|
+ fmt.Println("----(param *xuguParse) assertParamName 判断参数名结束")
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func (param *xuguParse) bindParamByPos(query string) string {
|
|
|
+ fmt.Printf("param: %#v \n", param)
|
|
|
+
|
|
|
+ for i := 0; i < param.param_count; i++ {
|
|
|
+ //sql语句里替换夫的下标, 替换为
|
|
|
+
|
|
|
+ query = strings.Replace(query, "?", param.Val[i].value, 1)
|
|
|
+
|
|
|
+ }
|
|
|
+ return query
|
|
|
+}
|
|
|
+
|
|
|
type SelectResult struct {
|
|
|
Field_Num uint32
|
|
|
Fields []FieldDescri
|
|
|
Values [][]ValueData //[字段][字段所有值]
|
|
|
+ rowIdx int
|
|
|
}
|
|
|
|
|
|
type FieldDescri struct {
|
|
@@ -312,17 +327,74 @@ type ValueData struct {
|
|
|
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 int
|
|
|
+ Args []ArgDescri
|
|
|
+}
|
|
|
+
|
|
|
+type ArgDescri struct {
|
|
|
+ ArgNameLen int
|
|
|
+ ArgName string
|
|
|
+ ArgNo int
|
|
|
+ ArgDType int
|
|
|
+ ArgPreciScale int
|
|
|
+}
|
|
|
+
|
|
|
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.BigEndian.Uint32(readBuf.readNext(4))
|
|
|
+ Field_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
|
data.Field_Num = Field_Num
|
|
|
+ data.rowIdx = 0
|
|
|
fmt.Println("Field_Num: ", data.Field_Num)
|
|
|
|
|
|
//获取字段信息
|
|
@@ -331,80 +403,219 @@ func parseSelectResult(readBuf buffer) (*SelectResult, error) {
|
|
|
field := FieldDescri{}
|
|
|
|
|
|
//Field_Name_Len
|
|
|
- field.FieldNameLen = int(binary.BigEndian.Uint32(readBuf.readNext(4)))
|
|
|
- fmt.Println("FieldNameLen: ", field.FieldNameLen)
|
|
|
-
|
|
|
+ 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))
|
|
|
- fmt.Println("FieldName: ", field.FieldName)
|
|
|
-
|
|
|
+ field.FieldName = string(readBuf.readNext(field.FieldNameLen, false))
|
|
|
+ fmt.Println("field.Field_Name: ", field.FieldName)
|
|
|
//Field_DType:
|
|
|
- field.FieldType = fieldType(binary.BigEndian.Uint32(readBuf.readNext(4)))
|
|
|
- fmt.Println("FieldType: ", field.FieldType)
|
|
|
-
|
|
|
+ field.FieldType = fieldType(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
|
|
|
+ fmt.Println("field.FieldType: ", field.FieldType)
|
|
|
//Field_Preci_Scale:
|
|
|
- field.FieldPreciScale = int(binary.BigEndian.Uint32(readBuf.readNext(4)))
|
|
|
- fmt.Println("FieldPreciScale: ", field.FieldPreciScale)
|
|
|
+ field.FieldPreciScale = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
|
|
|
+ fmt.Println("field.FieldPreciScale: ", field.FieldPreciScale)
|
|
|
//Field_Flag:
|
|
|
- field.FieldFlag = int(binary.BigEndian.Uint32(readBuf.readNext(4)))
|
|
|
- fmt.Println("FieldFlag: ", field.FieldFlag)
|
|
|
-
|
|
|
+ field.FieldFlag = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
|
|
|
+ fmt.Println("field.FieldFlag: ", field.FieldFlag)
|
|
|
data.Fields = append(data.Fields, field)
|
|
|
}
|
|
|
- fmt.Println("data的字段总数: ", data.Field_Num)
|
|
|
- for i, v := range data.Fields {
|
|
|
- fmt.Println("data的内容: ", i, v.FieldName)
|
|
|
- }
|
|
|
|
|
|
data.Values = make([][]ValueData, data.Field_Num)
|
|
|
|
|
|
- //获取字段的行值
|
|
|
+ //获取字段的行值,并判断类型
|
|
|
// 使用 Peek 方法检查下一个字节是否为'R'或'K'
|
|
|
+ fmt.Println("\n\n=========开始获取行数据=================================")
|
|
|
char := readBuf.peekChar()
|
|
|
- fmt.Println("是否为R: ", string(char))
|
|
|
+ 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.BigEndian.Uint32(readBuf.readNext(4))
|
|
|
- // fmt.Println("Col_len: ", col.Col_len)
|
|
|
-
|
|
|
- col.Col_Data = readBuf.readNext(int(col.Col_len))
|
|
|
- fmt.Println("Col_Data: ", string(col.Col_Data))
|
|
|
- data.Values[colIdx] = append(data.Values[colIdx], col)
|
|
|
- colIdx++
|
|
|
- char := readBuf.peekChar()
|
|
|
- if char == 'R' {
|
|
|
- fmt.Println("--=char3: ", string(readBuf.peekChar()))
|
|
|
- readBuf.idx++
|
|
|
- colIdx = 0
|
|
|
- continue
|
|
|
- } else if char == 'K' {
|
|
|
- fmt.Println("--=char4: ", string(readBuf.peekChar()))
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
+ //获取数据的大小
|
|
|
+ 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
|
|
|
|
|
|
- }
|
|
|
- fmt.Println("data的内容: ", data)
|
|
|
- for i := 0; i < int(data.Field_Num); i++ {
|
|
|
- for j := 0; j < len(data.Values[i]); j++ {
|
|
|
- fmt.Printf("data.Values[%d]: %v\n", i, (data.Values[i][j].Col_Data))
|
|
|
- }
|
|
|
+ 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 data, nil
|
|
|
+ return nil, errors.New("parseInsertResult error")
|
|
|
}
|
|
|
|
|
|
-func parseInsertResult(readBuf buffer) (*SelectResult, 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(reader *bufio.Reader) (*FormArgDescri, error) {
|
|
|
+ argNum, err := readInt32(reader)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ formArgDescri := &FormArgDescri{ArgNum: argNum}
|
|
|
+ for i := 0; i < argNum; i++ {
|
|
|
+ argDescri := ArgDescri{}
|
|
|
+ argDescri.ArgNameLen, err = readInt32(reader)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ argDescri.ArgName, err = readString(reader, argDescri.ArgNameLen)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ argDescri.ArgNo, err = readInt32(reader)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ argDescri.ArgDType, err = readInt32(reader)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ argDescri.ArgPreciScale, err = readInt32(reader)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ formArgDescri.Args = append(formArgDescri.Args, argDescri)
|
|
|
+ }
|
|
|
+ return formArgDescri, nil
|
|
|
}
|