|
@@ -1,13 +1,13 @@
|
|
|
package xugu
|
|
|
|
|
|
import (
|
|
|
- "bufio"
|
|
|
"database/sql/driver"
|
|
|
"encoding/binary"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
+ "time"
|
|
|
)
|
|
|
|
|
|
type ParseParam interface {
|
|
@@ -30,19 +30,19 @@ type xuguValue struct {
|
|
|
islob bool
|
|
|
plob []byte
|
|
|
|
|
|
- // 绑定参数变量的值 ? = aa
|
|
|
- value string
|
|
|
- // length 通常指定要绑定的参数变量值的实际长度
|
|
|
- length int
|
|
|
+ //字段名
|
|
|
+ paramName []byte
|
|
|
+ //paramNameLength [2]byte
|
|
|
+ // 字段的实际值
|
|
|
+ value []byte
|
|
|
+ // 值的长度
|
|
|
+ valueLength int
|
|
|
|
|
|
// buff 通常指定要绑定的参数数据的内存缓冲区大小
|
|
|
- buff int
|
|
|
+ //buff int
|
|
|
|
|
|
- // ?号在 sql 语句中的位置下标
|
|
|
- types int
|
|
|
-
|
|
|
- // 返回代码
|
|
|
- rcode int
|
|
|
+ // 字段的类型
|
|
|
+ types fieldType
|
|
|
}
|
|
|
|
|
|
type xuguParse struct {
|
|
@@ -56,7 +56,7 @@ type xuguParse struct {
|
|
|
// 当参数绑定类型为按参数名称绑定时,param_names 是参数名称的集合
|
|
|
param_names []byte
|
|
|
|
|
|
- Val []xuguValue
|
|
|
+ values []xuguValue
|
|
|
// 当参数绑定类型为按参数占位符绑定时,position 标识参数的位置
|
|
|
position int
|
|
|
}
|
|
@@ -70,6 +70,7 @@ func (Parse *xuguParse) assertParamCount(query string) int {
|
|
|
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
|
|
@@ -106,8 +107,10 @@ func (Parse *xuguParse) assertBindType(query string) int {
|
|
|
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
|
|
|
}
|
|
|
|
|
@@ -116,7 +119,6 @@ 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 {
|
|
@@ -124,120 +126,107 @@ func (param *xuguParse) assertParamType(dV driver.Value, pos int) error {
|
|
|
}
|
|
|
|
|
|
S := strconv.FormatInt(srcv, 10)
|
|
|
- dest.value = S
|
|
|
- dest.length = strings.Count(S, "") - 1
|
|
|
- dest.buff = dest.length + 1
|
|
|
+ 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 = SQL_XG_C_CHAR
|
|
|
-
|
|
|
- // case float32:
|
|
|
- // srcv, ok := dV.(float64)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("float32")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
-
|
|
|
- // S := strconv.FormatFloat(srcv, 'f', 6, 64)
|
|
|
- // 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
|
|
|
-
|
|
|
- // case float64:
|
|
|
- // srcv, ok := dV.(float64)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("float64")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
-
|
|
|
- // S := strconv.FormatFloat(srcv, 'f', 15, 64)
|
|
|
- // 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
|
|
|
-
|
|
|
- // case bool:
|
|
|
- // srcv, ok := dV.(bool)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("bool")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
-
|
|
|
- // S := strconv.FormatBool(srcv)
|
|
|
- // 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
|
|
|
+ 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:
|
|
|
- srcv, ok := dV.(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
|
|
|
|
|
|
- dest.value = srcv
|
|
|
- dest.length = strings.Count(srcv, "") - 1
|
|
|
- dest.buff = dest.length + 1
|
|
|
+ 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 = SQL_XG_C_CHAR
|
|
|
+ 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 {
|
|
|
|
|
|
- if dest.length == 0 {
|
|
|
- dest.length = 1
|
|
|
+ return errors.New("assertParamType []byte error")
|
|
|
}
|
|
|
|
|
|
- // case time.Time:
|
|
|
- // srcv, ok := dV.(time.Time)
|
|
|
- // if !ok {
|
|
|
- // news := errorNews("time.Time")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
-
|
|
|
- // tm := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d",
|
|
|
- // srcv.Year(), int(srcv.Month()), srcv.Day(),
|
|
|
- // srcv.Hour(), srcv.Minute(), srcv.Second())
|
|
|
-
|
|
|
- // dest.value = C.CString(tm)
|
|
|
- // dest.length = C.int(strings.Count(tm, "") - 1)
|
|
|
- // dest.buff = dest.length + 1
|
|
|
- // dest.islob = false
|
|
|
- // dest.types = SQL_XG_C_CHAR
|
|
|
-
|
|
|
- // 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 {
|
|
|
-
|
|
|
- // news := errorNews("[]byte")
|
|
|
- // return errors.New(news)
|
|
|
- // }
|
|
|
-
|
|
|
- // 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 = nil
|
|
|
- // dest.length = C.int(8)
|
|
|
- // dest.buff = C.int(8)
|
|
|
- // dest.islob = true
|
|
|
- // dest.types = SQL_XG_C_BLOB
|
|
|
+ // 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 = "xugusql"
|
|
|
- dest.length = 0
|
|
|
- dest.buff = strings.Count("xugusql", "")
|
|
|
+ dest.value = []byte("xugusql")
|
|
|
+ dest.valueLength = 0
|
|
|
dest.islob = false
|
|
|
- dest.types = SQL_XG_C_CHAR
|
|
|
+ dest.types = fieldType_CHAR
|
|
|
|
|
|
default:
|
|
|
/* OTHER DATA TYPE */
|
|
@@ -245,7 +234,7 @@ func (param *xuguParse) assertParamType(dV driver.Value, pos int) error {
|
|
|
}
|
|
|
|
|
|
param.position = pos
|
|
|
- param.Val = append(param.Val, dest)
|
|
|
+ param.values = append(param.values, dest)
|
|
|
|
|
|
return nil
|
|
|
}
|
|
@@ -291,17 +280,19 @@ func (param *xuguParse) assertParamName(query string) error {
|
|
|
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, "?", param.Val[i].value, 1)
|
|
|
+ query = strings.Replace(query, "?", string(param.values[i].value), 1)
|
|
|
|
|
|
}
|
|
|
return query
|
|
@@ -369,19 +360,19 @@ type Message struct {
|
|
|
}
|
|
|
|
|
|
type FormArgDescri struct {
|
|
|
- ArgNum int
|
|
|
+ ArgNum uint32
|
|
|
Args []ArgDescri
|
|
|
}
|
|
|
|
|
|
type ArgDescri struct {
|
|
|
- ArgNameLen int
|
|
|
- ArgName string
|
|
|
- ArgNo int
|
|
|
- ArgDType int
|
|
|
- ArgPreciScale int
|
|
|
+ ArgNameLen uint32
|
|
|
+ ArgName []byte
|
|
|
+ ArgNo uint32
|
|
|
+ ArgDType uint32
|
|
|
+ ArgPreciScale uint32
|
|
|
}
|
|
|
|
|
|
-func parseSelectResult(readBuf buffer) (*SelectResult, error) {
|
|
|
+func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
|
|
|
fmt.Println("调用 parseSelectResult")
|
|
|
data := &SelectResult{}
|
|
|
|
|
@@ -425,6 +416,9 @@ func parseSelectResult(readBuf buffer) (*SelectResult, error) {
|
|
|
//获取字段的行值,并判断类型
|
|
|
// 使用 Peek 方法检查下一个字节是否为'R'或'K'
|
|
|
fmt.Println("\n\n=========开始获取行数据=================================")
|
|
|
+ defer func() {
|
|
|
+ fmt.Println("\n\n=========获取行数据结束=================================")
|
|
|
+ }()
|
|
|
char := readBuf.peekChar()
|
|
|
fmt.Println(" --char: ", string(char))
|
|
|
readBuf.idx++
|
|
@@ -506,7 +500,7 @@ func parseSelectResult(readBuf buffer) (*SelectResult, error) {
|
|
|
return data, nil
|
|
|
}
|
|
|
|
|
|
-func parseInsertResult(readBuf buffer) (*InsertResult, error) {
|
|
|
+func parseInsertResult(readBuf *buffer) (*InsertResult, error) {
|
|
|
|
|
|
//Rowid_Len
|
|
|
Rowid_Len := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
@@ -525,19 +519,19 @@ func parseInsertResult(readBuf buffer) (*InsertResult, error) {
|
|
|
return nil, errors.New("parseInsertResult error")
|
|
|
}
|
|
|
|
|
|
-func parseUpdateResult(readBuf buffer) (*UpdateResult, 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) {
|
|
|
+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) {
|
|
|
+func parseProcRet(readBuf *buffer) (*ProcRet, error) {
|
|
|
retDType := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
|
|
|
|
retDataLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
@@ -546,7 +540,7 @@ func parseProcRet(readBuf buffer) (*ProcRet, error) {
|
|
|
return &ProcRet{RetDType: retDType, RetDataLen: retDataLen, RetData: retData}, nil
|
|
|
}
|
|
|
|
|
|
-func parseOutParamRet(readBuf buffer) (*OutParamRet, error) {
|
|
|
+func parseOutParamRet(readBuf *buffer) (*OutParamRet, error) {
|
|
|
outParamNo := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
|
|
|
|
outParamDType := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
@@ -563,15 +557,16 @@ func parseOutParamRet(readBuf buffer) (*OutParamRet, error) {
|
|
|
}, nil
|
|
|
}
|
|
|
|
|
|
-func parseErrInfo(readBuf buffer) (*ErrInfo, error) {
|
|
|
+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) {
|
|
|
+func parseWarnInfo(readBuf *buffer) (*WarnInfo, error) {
|
|
|
warnStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
|
|
|
|
warnStr := readBuf.readNext(int(warnStrLen), false)
|
|
@@ -579,7 +574,7 @@ func parseWarnInfo(readBuf buffer) (*WarnInfo, error) {
|
|
|
return &WarnInfo{WarnStrLen: warnStrLen, WarnStr: warnStr}, nil
|
|
|
}
|
|
|
|
|
|
-func parseMessage(readBuf buffer) (*Message, error) {
|
|
|
+func parseMessage(readBuf *buffer) (*Message, error) {
|
|
|
msgStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
|
|
|
|
|
|
msgStr := readBuf.readNext(int(msgStrLen), false)
|
|
@@ -587,35 +582,25 @@ func parseMessage(readBuf buffer) (*Message, error) {
|
|
|
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)
|
|
|
+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
|
|
|
}
|