GTong 10 months ago
parent
commit
c526160014

+ 15 - 0
.vscode/launch.json

@@ -0,0 +1,15 @@
+{
+    // 使用 IntelliSense 了解相关属性。 
+    // 悬停以查看现有属性的描述。
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Package",
+            "type": "go",
+            "request": "launch",
+            "mode": "auto",
+            "program": "${workspaceFolder}/main.go"
+        }
+    ]
+}

+ 108 - 2
main.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"database/sql"
+	"fmt"
 	"log"
 	_ "xugu_driver/xugu"
 )
@@ -14,6 +15,14 @@ func main() {
 		log.Fatal(err)
 	}
 
+	// err = db.Ping()
+	// if err != nil {
+	// 	fmt.Printf("connect xugu dbms ... failed\n")
+	// } else {
+
+	// 	fmt.Printf("connect xugu dbms ... ok\n")
+	// }
+
 	// stmt, err := db.Prepare("SELECT ? FROM gotest2;")
 	// stmt.Query("1")
 	//查询
@@ -41,9 +50,106 @@ func main() {
 	// }
 
 	//消息类型为E
-	r, err := db.Exec("drop table ta3;drop table ta33; ")
-	r.RowsAffected()
+	// r, err := db.Exec("drop table ta3;drop table ta4;")
+	// r.RowsAffected()
 	// db.Exec("INSERT INTO  gotest VALUES('gt3');")
+
+	//db.Prepare
+	// stmt, err := db.Prepare("INSERT INTO gotest values(?);")
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	// ret, err := stmt.Exec("gt32")
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	// fmt.Println("ret", ret)
+
+	//db.Exec
+	//db.Exec("INSERT INTO gotest2 VALUES(1, 'gt3');")
+
+	//db.Query
+	// rows, err := db.Query("select * from gotest")
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	// var cols []string
+	// cols, err = rows.Columns()
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	// pvals := make([]interface{}, len(cols))
+	// for key, _ := range pvals {
+	// 	dest := make([]byte, 216)
+	// 	pvals[key] = &dest
+	// } /* end for */
+	// for rows.Next() {
+	// 	err = rows.Scan(pvals...)
+	// 	if err != nil {
+	// 		log.Fatal(err)
+	// 	}
+	// 	for _, v := range pvals {
+	// 		fmt.Printf("%s\t", string(*(v.(*[]byte))))
+	// 	}
+	// 	fmt.Printf("\n")
+	// }
+	// rows.Close()
+
+	//插入blob
+	//db.Exec("create table goblob(a int, b blob);")
+	// 打开文件
+	// file, err := os.Open("todo.txt")
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	// defer file.Close()
+	// 读取文件内容
+	// content, err := io.ReadAll(file)
+	// if err != nil {
+	// 	log.Fatal(err)
+	// }
+	//db.Exec("insert into goblob values(1, ?);", content)
+	//stmt方式插入
+	// stmt, err := db.Prepare("insert into goblob values(1, ?);")
+	// if err != nil {
+	// 	fmt.Println("error", err)
+	// }
+	// _, err = stmt.Exec(content)
+	// if err != nil {
+	// 	fmt.Println("error", err)
+	// }
+
+	//查询blob
+	rows, err := db.Query("select b from goblob;")
+	if err != nil {
+		fmt.Println("error", err)
+	}
+	var cols []string
+	cols, err = rows.Columns()
+	if err != nil {
+		log.Fatal(err)
+	}
+	pvals := make([]interface{}, len(cols))
+	for key, _ := range pvals {
+		dest := make([]byte, 216)
+
+		pvals[key] = &dest
+	} /* end for */
+
+	for rows.Next() {
+		fmt.Println("rows.Next()")
+		err = rows.Scan(pvals...)
+		if err != nil {
+			log.Fatal(err)
+		}
+		for _, v := range pvals {
+			fmt.Printf("aa %s\t", string(*(v.(*[]byte))))
+		}
+
+		fmt.Printf("\n")
+	}
+
+	rows.Close()
 	db.Close()
 
 }

+ 7 - 0
select A.ini

@@ -106,3 +106,10 @@ R\x00\x00\x00\x01
 \x01
 K
 
+
+
+ [
+ 63
+ Command_len
+0 0 0 9
+ 63 32 71 84 79 78 71 48 32 0 0 0 0 0 0 0 0 0 49 0 30 0 0 0 6 103 111 116 101 115 116 0 0 0 0 49 0 30 0 0 0 4 103 116 51 50]

+ 7 - 4
xugu/buffer.go

@@ -40,6 +40,7 @@ func (b *buffer) store(buf []byte) error {
 
 func (b *buffer) peekChar() byte {
 	ret := b.buf[b.idx]
+	//	fmt.Println("peekChar内部的: ", b.buf[b.idx:])
 	return ret
 }
 
@@ -57,16 +58,18 @@ func (b *buffer) readNext(need int, reverse bool) []byte {
 
 	offset := b.idx
 	b.idx += need
-	fmt.Println("readNext: 大端值", b.buf[offset:b.idx], " - ", string(b.buf[offset:b.idx]))
+
 	//fmt.Println("readNext: ", b.buf[offset:b.idx])
 	if reverse {
-		tmp2 := b.buf[offset:b.idx]
-		fmt.Println("readNext: 转换小端前", tmp2, " - ", string(tmp2))
+		//	tmp2 := b.buf[offset:b.idx]
+		//fmt.Println("readNext: 转换小端前", tmp2, " - ", string(tmp2))
 		tmp := reverseBytes(b.buf[offset:b.idx])
-		fmt.Println("readNext: 转换小端后", tmp, " - ", string(tmp))
+		//	fmt.Println("readNext: 转换小端后", tmp, " - ", string(tmp))
 
 		return tmp
 	} else {
+		//	fmt.Println("readNext: 没有转换:", b.buf[offset:b.idx])
+		//	fmt.Println("readNext: 没有转换:", string(b.buf[offset:b.idx]))
 		return b.buf[offset:b.idx]
 	}
 

+ 124 - 28
xugu/xugu_sock_recv.go → xugu/discard.go

@@ -8,6 +8,130 @@ import (
 	"net"
 )
 
+// ----------------------------------------------------------------------------------------------------
+type SrvResponse struct {
+	FormArgDescri []*FormArgDescri
+	SelectResult  []*SelectResult
+	InsertResult  []*InsertResult
+	UpdateResult  []*UpdateResult
+	DeleteResult  []*DeleteResult
+	ProcRet       []*ProcRet
+	OutParamRet   []*OutParamRet
+	ErrInfo       []*ErrInfo
+	WarnInfo      []*WarnInfo
+	Message       []*Message
+}
+
+// func parseResponse(conn net.Conn) (*SrvResponse, error) {
+// 	response := &SrvResponse{}
+// 	reader := bufio.NewReader(conn)
+
+// 	for {
+// 		msgType, err := reader.ReadByte()
+// 		if err != nil {
+// 			return nil, err
+// 		}
+
+// 		switch msgType {
+// 		case '$':
+// 			argDescri, err := parseFormArgDescri(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.FormArgDescri = append(response.FormArgDescri, argDescri)
+
+// 		case 'I':
+// 			insertResult, err := parseInsertResult(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.InsertResult = append(response.InsertResult, insertResult)
+// 		case 'U':
+// 			updateResult, err := parseUpdateResult(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.UpdateResult = append(response.UpdateResult, updateResult)
+// 		case 'D':
+// 			deleteResult, err := parseDeleteResult(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.DeleteResult = append(response.DeleteResult, deleteResult)
+// 		case 'O':
+// 			procRet, err := parseProcRet(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.ProcRet = append(response.ProcRet, procRet)
+// 		case 'P':
+// 			outParamRet, err := parseOutParamRet(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.OutParamRet = append(response.OutParamRet, outParamRet)
+// 		case 'E':
+// 			errInfo, err := parseErrInfo(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.ErrInfo = append(response.ErrInfo, errInfo)
+// 		case 'W':
+// 			warnInfo, err := parseWarnInfo(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.WarnInfo = append(response.WarnInfo, warnInfo)
+// 		case 'M':
+// 			message, err := parseMessage(reader)
+// 			if err != nil {
+// 				return nil, err
+// 			}
+// 			response.Message = append(response.Message, message)
+// 		case 'K':
+// 			return response, nil
+// 		default:
+// 			return nil, fmt.Errorf("未知的消息类型: %v", msgType)
+// 		}
+// 	}
+// }
+
+// 解析函数的实现,例如 parseFormArgDescri 等
+
+func readString(reader *bufio.Reader, length int) (string, error) {
+	bytes := make([]byte, length)
+	_, err := reader.Read(bytes)
+	return string(bytes), err
+}
+
+func parseFieldDescri(reader *bufio.Reader) (FieldDescri, error) {
+	fieldDescri := FieldDescri{}
+	var err error
+
+	fieldDescri.FieldNameLen, err = readInt32(reader)
+	if err != nil {
+		return fieldDescri, err
+	}
+	fieldDescri.FieldName, err = readString(reader, fieldDescri.FieldNameLen)
+	if err != nil {
+		return fieldDescri, err
+	}
+	// fieldDescri.FieldType, err = fieldType(reader)
+	// if err != nil {
+	// 	return fieldDescri, err
+	// }
+	fieldDescri.FieldPreciScale, err = readInt32(reader)
+	if err != nil {
+		return fieldDescri, err
+	}
+	fieldDescri.FieldFlag, err = readInt32(reader)
+	if err != nil {
+		return fieldDescri, err
+	}
+
+	return fieldDescri, nil
+}
+
 func xgSockRecvCommand(pConn *xuguConn) {
 
 }
@@ -183,34 +307,6 @@ func readInt32(reader *bufio.Reader) (int, error) {
 	return int(value), err
 }
 
-func recvParamsInfo2(pConn *xuguConn, params *XGCSParam) (int, error) {
-	var paramNum uint32
-	var i_ord []uint32
-	var i_type []uint32
-	var i_prescale []uint32
-	pNames := make([][]byte, paramNum)
-	rhRecvInt32(pConn, &paramNum)
-	params.ParamNum = paramNum
-
-	for n := uint32(0); n < paramNum; n++ {
-		// 读取名称
-		rhRecvStr(pConn, &pNames[n])
-		// 读取序号
-		rhRecvInt32(pConn, &i_ord[n])
-		// 读取类型
-		rhRecvInt32(pConn, &i_type[n])
-		// 读取预缩放值
-		rhRecvInt32(pConn, &i_prescale[n])
-	}
-
-	params.VParamName = pNames
-	params.VParamNo = i_ord
-	params.VType = i_type
-	params.VParamSize = i_prescale
-
-	return 0, nil
-}
-
 //接收结果集
 //int  recv_Query_Rs(Conn_Attrs* p_conn,Result** pp_res,int*field_num,int64* rowcount,int* effected_num)
 /* recv_Query_Rs :

+ 181 - 12
xugu/xugu_conn.go

@@ -2,6 +2,7 @@ package xugu
 
 import (
 	"bytes"
+	"context"
 	"database/sql/driver"
 	"errors"
 	"fmt"
@@ -21,7 +22,7 @@ type xuguConn struct {
 	prepareNo   int //fashengqi
 	prepareName string
 	//presPrepareCata *Result
-	params *XGCSParam
+
 	errStr []byte
 
 	sendBuff bytes.Buffer
@@ -49,21 +50,27 @@ type dsnConfig struct {
 	Version        string
 }
 
-func (xgConn *xuguConn) get_error() error {
+func (xgConn *xuguConn) Get_error() error {
 
 	return nil
 }
 
+//SELECT 1 FROM DUAL
+
 func (xgConn *xuguConn) Begin() (driver.Tx, error) {
 
 	return nil, nil
 
 }
 
-func (xgConn *xuguConn) Prepare(query string) (driver.Stmt, error) {
+var prepareCount = 0
+
+func (xgConn *xuguConn) Prepare(sql string) (driver.Stmt, error) {
 	fmt.Println(">>>>>(xgConn *xuguConn) Prepare(query string)")
+	prepareName := fmt.Sprintf("GTONG%d", prepareCount)
+
 	//判断sql类型
-	switch switchSQLType(query) {
+	switch switchSQLType(sql) {
 	case SQL_PROCEDURE:
 		return nil, errors.New("Prepare does not support stored procedures")
 	case SQL_UNKNOWN:
@@ -72,17 +79,37 @@ func (xgConn *xuguConn) Prepare(query string) (driver.Stmt, error) {
 		return nil, errors.New("Prepare does not support DDL.")
 	}
 
-	stmt := &xuguStmt{
-		stmt_conn:   xgConn,
-		prepared:    true,
-		prename:     make([]byte, 128),
-		curopend:    false,
-		curname:     make([]byte, 128),
+	//参数个数
+	parser := &xuguParse{
+		bind_type:   0,
 		param_count: 0,
-		result:      nil,
-		mysql:       query,
+		position:    0,
+	}
+	count := parser.assertParamCount(sql)
+	parser.param_count = count
+	fmt.Println("语句 参数个数:", count)
+
+	//发送创建prepare
+	err := xuguPrepare(xgConn, sql, prepareName)
+	if err != nil {
+		return nil, err
 	}
 
+	//sockSendPutStatement(xgConn, []byte(sql))
+
+	stmt := &xuguStmt{
+		stmt_conn:  xgConn,
+		prepared:   true,
+		prename:    make([]byte, 128),
+		curopend:   false,
+		curname:    make([]byte, 128),
+		paramCount: count,
+		mysql:      sql,
+		parser:     parser,
+	}
+	prepareName = fmt.Sprintf("? %s ", prepareName)
+	stmt.prename = []byte(prepareName)
+	xgConn.prepareName = prepareName
 	return stmt, nil
 }
 
@@ -95,3 +122,145 @@ func (xgConn *xuguConn) Close() error {
 	}
 	return nil
 }
+
+func (xgConn *xuguConn) Exec(sql string,
+	args []driver.Value) (driver.Result, error) {
+	fmt.Printf(">>> (xgConn *xuguConn) Exec: %s, %v\n", sql, args)
+
+	if switchSQLType(sql) == SQL_SELECT {
+		return nil, errors.New("The executed SQL statement is not a SELECT")
+	}
+	//有参数传进来
+	if len(args) != 0 {
+		//创建prepare
+		_, err := xgConn.Prepare(sql)
+		if err != nil {
+			return nil, err
+		}
+
+		//
+		parser := &xuguParse{
+			bind_type:   0,
+			param_count: len(args),
+			position:    0,
+		}
+
+		for pos, param := range args {
+			parser.assertParamType(param, pos)
+			//fmt.Printf("Field Name: %s, Field Type: %s, Field Value: %v\n", v1, v1, v1)
+		}
+		sockSendPutStatement(xgConn, []byte(xgConn.prepareName), &parser.values, len(args))
+		XGC_Execute(xgConn)
+
+		//处理服务器返回
+		xgConn.conn.Read(xgConn.readBuff.buf)
+		readBuf := &xgConn.readBuff
+		fmt.Println("Message from server EXEC:", readBuf.buf[readBuf.idx:])
+		fmt.Println("Message from server EXEC:", string(xgConn.readBuff.buf))
+
+		rs, err := parseMsg(readBuf, xgConn)
+		if err != nil {
+			return nil, err
+		}
+		return rs, nil
+	}
+
+	rs, err := xgConn.exec(sql)
+	if err != nil {
+		return nil, err
+	}
+	return rs, nil
+
+}
+
+func (xgConn *xuguConn) exec(sql string) (driver.Result, error) {
+	sockSendPutStatement(xgConn, []byte(sql), nil, 0)
+	XGC_Execute(xgConn)
+
+	//处理服务器返回
+	xgConn.conn.Read(xgConn.readBuff.buf)
+	readBuf := &xgConn.readBuff
+	fmt.Println("Message from server EXEC:", readBuf.buf[readBuf.idx:])
+	fmt.Println("Message from server EXEC:", string(xgConn.readBuff.buf))
+
+	rs, err := parseMsg(readBuf, xgConn)
+	if err != nil {
+		return nil, err
+	}
+	return rs, nil
+}
+
+func (xgConn *xuguConn) Query(sql string,
+	args []driver.Value) (driver.Rows, error) {
+	fmt.Println(">>> (xgConn *xuguConn)  Query")
+
+	if switchSQLType(sql) != SQL_SELECT {
+		return nil, errors.New("The executed SQL statement is not a SELECT")
+	}
+
+	parser := &xuguParse{
+		bind_type:   0,
+		param_count: 0,
+		position:    0,
+	}
+
+	if len(args) != 0 {
+
+		for pos, param := range args {
+
+			err := parser.assertParamType(param, pos)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		if len(parser.values) != parser.assertParamCount(sql) {
+			return nil, errors.New("The number of parameters does not match")
+		}
+
+	}
+
+	//最终发送消息给服务器
+	sockSendPutStatement(xgConn, []byte(sql), nil, 0)
+	XGC_Execute(xgConn)
+
+	//----------------处理服务器查询返回
+
+	xgConn.conn.Read(xgConn.readBuff.buf)
+
+	//fmt.Println("Message from server:", (buffer[:n]))
+	fmt.Println("Message from server:", string(xgConn.readBuff.buf))
+	//fmt.Println("\nMessage from server2:", (stmt.stmt_conn.readBuff.buf))
+	results, err := parseSelectResult(&xgConn.readBuff)
+	if err != nil {
+		fmt.Println("parseSelectResult parseSelectResult err", err.Error())
+		return nil, err
+	}
+	rows := &xuguRows{
+		rows_conn:   xgConn,
+		results:     results,
+		lastRowRelt: int(0),
+		lastRelt:    int(0),
+		prepared:    false,
+	}
+
+	return rows, nil
+}
+
+func (xgConn *xuguConn) Ping(ctx context.Context) error {
+	sockSendPutStatement(xgConn, []byte("select count(*) from dual;"), nil, 0)
+	XGC_Execute(xgConn)
+	xgConn.conn.Read(xgConn.readBuff.buf)
+
+	//fmt.Println("Message from server:", (buffer[:n]))
+	fmt.Println("Message from server:", string(xgConn.readBuff.buf))
+	//fmt.Println("\nMessage from server2:", (stmt.stmt_conn.readBuff.buf))
+	_, err := parseSelectResult(&xgConn.readBuff)
+	if err != nil {
+		fmt.Println("parseSelectResult parseSelectResult err", err.Error())
+		return err
+	}
+	xgConn.readBuff.idx = 0
+	xgConn.readBuff.buf = make([]byte, 2048)
+	return nil
+}

+ 1 - 0
xugu/xugu_connector.go

@@ -55,6 +55,7 @@ func (conntor *connector) Connect(ctx context.Context) (driver.Conn, error) {
 	xgConn.Type = HT_CONN
 	xgConn.readBuff = newBuffer(xgConn.conn)
 	fmt.Println("连接串为: ", conntor.dsn)
+	
 	err = xgSockOpenConn(ctx, xgConn)
 	if err != nil {
 		return nil, err

+ 4 - 4
xugu/xugu_define.go

@@ -45,10 +45,10 @@ const (
 	SQL_PARAM_INPUTOUTPUT int = 3
 	SQL_PARAM_RETURNVALUE int = 6
 
-	SQL_XG_C_CHAR int = 2
-	SQL_XG_C_CLOB int = 41
-	SQL_XG_C_BLOB int = 42
-	SQL_XG_C_NULL int = -11
+	// SQL_XG_C_CHAR int = 2
+	// SQL_XG_C_CLOB int = 41
+	// SQL_XG_C_BLOB int = 42
+	// SQL_XG_C_NULL int = -11
 
 	BIND_PARAM_BY_NAME int = 2
 	BIND_PARAM_BY_POS  int = 1

+ 26 - 0
xugu/xugu_fields.go

@@ -2,6 +2,8 @@ package xugu
 
 import (
 	"database/sql"
+	"database/sql/driver"
+	"fmt"
 	"reflect"
 	"time"
 )
@@ -233,3 +235,27 @@ var (
 	scanTypeUint64    = reflect.TypeOf(uint64(0))
 	scanTypeBool      = reflect.TypeOf(bool(false))
 )
+
+func processValue(value driver.Value) {
+	switch v := value.(type) {
+	case nil:
+		fmt.Println("Value is nil")
+	case int64:
+		fmt.Printf("Value is int64: %d\n", v)
+	case float64:
+		fmt.Printf("Value is float64: %f\n", v)
+	case bool:
+		fmt.Printf("Value is bool: %t\n", v)
+	case []byte:
+		fmt.Printf("Value is []byte: %x\n", v)
+	case string:
+		fmt.Printf("Value is string: %s\n", v)
+	case time.Time:
+		fmt.Printf("Value is time.Time: %s\n", v)
+	case driver.Rows:
+		fmt.Println("Value is driver.Rows")
+		// You can further process the rows here
+	default:
+		fmt.Println("Unknown type")
+	}
+}

+ 0 - 346
xugu/xugu_param.go

@@ -1,346 +0,0 @@
-package xugu
-
-import "fmt"
-
-//定义 XGCSParam 结构体
-type XGCSParam struct {
-	Type           HANDLE_TYPE // 句柄类型
-	ParamNum       uint32      // 单行参数数量
-	PResourceNum   int         // 参数名称资源数量,步长128
-	ParamArraySize int         // 参数数组长度(数组大小)
-	ValueP         []byte      // 实际参数指针数组,指向参数地址
-	VType          []uint32    // 参数类型:数组,参数数量
-	VParamSize     []uint32    // 参数缓冲区长度,参数数量
-	VDbType        *int        // 参考数据库数据类型,参数数量
-	VActuallenp    [][]int     // 参数数据实际大小数组,[参数数组大小][参数数量]
-	VParamName     [][]byte    // 参数名称
-	VParamNo       []uint32    // 参数序列数组
-	VInOut         []int       // 输入输出类型
-	ErrStr         []byte      // 错误字符串
-	MemType        int         // 内存使用模式(0:引用,1:驱动程序分配)
-	ImpExpType     int         // 0 隐式创建,1 显式创建,2 由服务器提供的准备语句获取
-}
-
-//按序号绑定
-/*=====================================
-p_conn     连接句柄
-param_no   参数号: 从1开始
-param_type 参数输入输出型
-datatype   参数数据类型
-value      参数值
-param_size 单个参数的空间大小 buffer
-rlen_val   具体的每个参数 的对应实际大小
-======================================*/
-func xgSockBindparamByPos(pconn *xuguConn, param_no int, param_type int, datatype int, value []byte, param_size int, rlen_val []int) int {
-	if pconn.Type == HT_CONN {
-		if pconn.params == nil {
-			pconn.params = &XGCSParam{Type: HT_PARAMS}
-		}
-		if param_no > 4000 {
-			pconn.errStr = []byte(fmt.Sprintf("[EC051]Error invalid param NO %d out of range paramnum", param_no))
-			return -51
-		}
-		if !(param_type == 1 || param_type == 2 || param_type == 3 || param_type == 6) {
-			pconn.errStr = []byte(fmt.Sprintf("[EC052]Error invalid param type %d", param_type))
-			return -52
-		}
-		if param_no < 1 {
-			pconn.errStr = []byte(fmt.Sprintf("[EC054]Error param_no  param seq %d invalid", param_no))
-			return -54
-		}
-	} else if pconn.params.Type == HT_PARAMS {
-		if param_no > 4000 {
-			pconn.params.ErrStr = []byte(fmt.Sprintf("[EC051]Error invalid param NO %d out of range paramnum", param_no))
-			//set error 参数绑定序列值 超过合理范围
-			return -51
-		}
-		if !(param_type == 1 || param_type == 2 || param_type == 3 || param_type == 6) {
-			pconn.params.ErrStr = []byte(fmt.Sprintf("[EC052]Error invalid param type %d", param_type))
-			return -52 //参数绑定类型非法
-		}
-		if param_no < 1 {
-			pconn.errStr = []byte(fmt.Sprintf("[EC054]Error param_no  param seq %d invalid", param_no))
-			return -54
-		}
-	} else {
-		//invalid ptr set
-		return XG_INVALID_ARG
-	}
-	ret := xgSockBindParamsByPos(*pconn.params, param_no, param_type, datatype, value, param_size, rlen_val)
-
-	if ret < 0 {
-		if ret == -55 {
-			pconn.errStr = []byte(fmt.Sprintf("[EC055]Error bindparam jump long %d invalid", ret))
-			return -55
-		} else if ret == -8 {
-			pconn.errStr = []byte(fmt.Sprintf("[EC056]Error bindparam unsurpported ret %d invalid", ret))
-			return -8
-		}
-	}
-	return ret
-}
-
-func xgSockBindParamsByPos(pParams XGCSParam, param_no int, param_type int, datatype int, value []byte, param_size int, rlen_val []int) int {
-	ipar := param_no
-	ipar--
-	if pParams.ParamNum == 0 { // 初始化空间
-		pParams.PResourceNum = 128
-
-		pParams.VType = make([]uint32, 128)
-		pParams.VParamSize = make([]uint32, 128)
-		//pParams.VDbType = make([][]int, 128)
-		pParams.VActuallenp = make([][]int, 128)
-		pParams.VParamNo = make([]uint32, 128)
-		pParams.VInOut = make([]int, 128)
-		pParams.VParamName = nil
-	}
-
-	if int(pParams.ParamNum) < param_no { //分配空间(加增)
-		if pParams.PResourceNum < param_no { //资源分配
-			if pParams.PResourceNum+128 < param_no {
-				return -55 // set error  参数绑定跳跃度过大
-			}
-		}
-		//go 切片会自动分配内存 切片扩容机制
-
-	}
-
-	if param_type == 6 {
-		//函数返回值绑定
-		pParams.VParamNo[uint32(ipar)] = uint32(ipar) //意义不大 或者可以改成valid
-		pParams.VType[uint32(ipar)] = uint32(datatype)
-		pParams.ValueP = value
-		pParams.VParamSize[uint32(ipar)] = uint32(param_size)
-		pParams.VActuallenp[uint32(ipar)] = rlen_val
-		pParams.VInOut[uint32(ipar)] = param_type
-
-	} else if param_type == 1 { //input
-
-		pParams.VParamNo[uint32(ipar)] = uint32(ipar) //意义不大 或者可以改成valid
-		pParams.VType[uint32(ipar)] = uint32(datatype)
-		//tmp ===================== value cpoy ================================
-		pParams.ValueP = value
-		pParams.VActuallenp[uint32(ipar)] = rlen_val //tmp end
-		pParams.MemType = 1
-		pParams.VInOut[uint32(ipar)] = 1
-
-	} else if param_type == 2 || param_type == 3 { //output ||inoutput
-		pParams.VParamNo[uint32(ipar)] = uint32(ipar)
-		pParams.VType[uint32(ipar)] = uint32(datatype)
-
-		pParams.ValueP = value
-		pParams.VParamSize[uint32(ipar)] = uint32(param_size) //buff长度
-		pParams.VActuallenp[uint32(ipar)] = rlen_val
-		pParams.VInOut[uint32(ipar)] = param_type
-	} else { //3
-		return -8 //尚未实现
-		//参数绑定类型不合格
-	}
-	return 0
-}
-
-//批量
-/*=============================================
-p_conn  连接句柄
-param_no  参数号: 从1开始
-param_type 参数输入输出型
-datatype 参数数据类型
-array_size 数组的大小长度
-array_value 参数值数组
-param_size 单个参数的空间大小 buffer
-rlen_val 具体的每个参数 的对应实际大小[与参数值大小一一对应]
-==============================================*/
-func xgSockBindParamArrayByPos(pConn *xuguConn, param_no int, param_num int, param_type int, datatype int, array_size int, array_value []byte, param_size int, rlen_val []int) int {
-	if pConn.Type == HT_CONN {
-		if pConn.params == nil {
-			pConn.params = new(XGCSParam)
-			pConn.params.Type = HT_PARAMS //imp_exp_type= 0;
-		}
-		if param_no > 4000 || param_num > 4000 || param_num < -1 {
-			//set error 参数绑定序列值 超过合理范围
-			pConn.errStr = []byte(fmt.Sprintf("[EC051]Error invalid param NO %d out of range paramnum", param_num))
-			return -51
-		}
-		if !(param_type == 1 || param_type == 2 || param_type == 3 || param_type == 6) {
-			pConn.errStr = []byte(fmt.Sprintf("[EC052]Error invalid param type %d", param_type))
-			return -52 //参数绑定类型非法
-		}
-		if param_no < 1 {
-			pConn.errStr = []byte(fmt.Sprintf("[EC054]Error param_no  param seq %d invalid", param_no))
-			return -54
-		}
-	} else if pConn.Type == HT_PARAMS {
-		//pParams := pConn.params
-		if param_no > 4000 {
-			pConn.params.ErrStr = []byte(fmt.Sprintf("[EC051]Error invalid param NO %d out of range paramnum", param_no))
-			return -51
-		}
-		if !(param_type == 1 || param_type == 2 || param_type == 3 || param_type == 6) {
-			pConn.params.ErrStr = []byte(fmt.Sprintf("[EC052]Error invalid param type %d", param_type))
-			return -52 //参数绑定类型非法
-		}
-		if param_no < 1 {
-			pConn.params.ErrStr = []byte(fmt.Sprintf("[EC054]Error param_no  param seq %d invalid", param_no))
-			return -54
-		}
-	} else {
-		return XG_INVALID_ARG
-	}
-	ret := xgSockBindParamsArrayByPos(pConn.params, param_no, param_num, param_type, datatype, array_size, array_value, param_size, rlen_val)
-	return ret
-}
-
-func xgSockBindParamsArrayByPos(pParams *XGCSParam, param_no int, param_num int, param_type int, datatype int, array_size int,
-	array_value []byte, param_size int, rlen_val []int) int {
-	ipar := param_no - 1
-	if pParams.ParamNum == 0 {
-		//以下部分需要重新封装 使得看起来比较代码简练
-
-		if param_num == 0 { //顶层资源 一次分配128
-			pParams.PResourceNum = 128
-
-			pParams.VType = make([]uint32, 128)
-			pParams.VParamSize = make([]uint32, 128)
-			//pParams.VDbType = make([][]int, 128)
-			pParams.VActuallenp = make([][]int, 128)
-			pParams.VParamNo = make([]uint32, 128)
-			pParams.VInOut = make([]int, 128)
-			pParams.VParamName = nil
-		} else { //已知参数列数
-			pParams.ParamArraySize = array_size //数组容量确定
-
-			pParams.VType = make([]uint32, param_num)
-			pParams.VParamSize = make([]uint32, param_num)
-			//pParams.VDbType = make([][]int, 128)
-			pParams.VActuallenp = make([][]int, param_num) //这个p_params->v_actuallenp[ipar][0]指向传入数组就行了
-			pParams.VParamNo = make([]uint32, param_num)
-			pParams.VInOut = make([]int, param_num)
-			//pParams.VParamName = nil
-		}
-	}
-
-	if pParams.ParamNum < uint32(param_no) {
-		if pParams.PResourceNum < param_no { //资源分配
-
-		}
-		pParams.ParamNum = uint32(param_no) //允许了中间的空洞
-
-	}
-
-	if param_type == 6 { //1236   in out inout return value
-		//函数返回值绑定
-
-	} else if param_type == 1 { //input
-		pParams.VParamNo[ipar] = uint32(param_no) ////意义不大 或者可以改成valid
-		pParams.VType[ipar] = uint32(datatype)
-
-		//off := 0
-		//ptrLen := 0 //varchar长度指示器
-		var ptr []byte
-		copy(pParams.VActuallenp[ipar], rlen_val)
-		if needCopyV(datatype) {
-			//m_ele_siz := getDbTypeLen(datatype)
-			copy(ptr, array_value)
-		} else if datatype == XG_C_CHAR || datatype == XG_C_NCHAR {
-			copy(ptr, array_value)
-		} else {
-			// ptr=(char*)malloc(param_size);//no
-			//memcpy(ptr,array_value,param_size);
-		}
-
-		for irow := 0; irow < array_size; irow++ {
-			switch datatype {
-			// case XG_C_INTEGER, XG_C_FLOAT:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-
-			// case XG_C_NCHAR, XG_C_CHAR:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-
-			// case XG_C_BIGINT, DATETIME_ASLONG:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			// case XG_C_DOUBLE:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			// case XG_C_NUMERIC:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			// case XG_C_DATE, XG_C_TIME, XG_C_DATETIME, XG_C_TIME_TZ, XG_C_DATETIME_TZ, XG_C_BINARY, XG_C_INTERVAL_YEAR_TO_MONTH, XG_C_INTERVAL_DAY_TO_SECOND:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			// case XG_C_SHORT:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			// case XG_C_TINYINT, XG_C_BOOL, XG_C_CHARN1:
-			// 	pParams.ValueP[irow][ipar] = ptr[off]
-			// 	off++
-			default:
-				fmt.Println("bindparam unsurpported datatype")
-				pParams.ErrStr = []byte(fmt.Sprintf("[EC058]Error bindparam unsurpported datatype %d invalid", datatype))
-				return -58
-			}
-
-		}
-		pParams.VParamSize[ipar] = uint32(param_size) //buff长度
-		pParams.VInOut[ipar] = 1
-	} else if param_type == 2 { //output
-		//	p_params->v_actuallenp[ipar]    = rlen_val;//这里之所以是引用传递 那是因为 out or inout 型时 需要反馈实际的参数的长度
-		return -8 //尚未实现
-	} else { //3
-		return -8 //尚未实现
-		//参数绑定类型不合格
-	}
-	return XG_OK
-}
-
-//按名绑定
-/*=====================================
-p_conn     连接句柄  2 p_conn  参数句柄(显式创建参数句柄)
-param_name   参数名: 当出现一样的参数名时,会进行覆盖但是不会报错
-param_type 参数输入输出型
-datatype   参数数据类型
-value      参数值
-param_size 单个参数的空间大小 buffer
-rlen_val   具体的每个参数 的对应实际大小
-======================================*/
-func xgSockBindParamByName(pConn *xuguConn, param_name []byte, param_type int, datatype int, void []byte, param_sizeint, rt_code *int, rlen_val []int) int {
-	pParams := pConn.params
-	if pConn.Type == HT_CONN {
-		if nil == pConn.params {
-
-			pConn.params = &XGCSParam{}
-			pConn.params.Type = HT_PARAMS //imp_exp_type= 0;
-		}
-		pParams = pConn.params
-	} else if pConn.Type == HT_PARAMS {
-		pParams = pConn.params
-	} else {
-		//invalid ptr set
-		return XG_INVALID_ARG
-	}
-	if !(param_type == 1 || param_type == 2 || param_type == 3 || param_type == 6) {
-		if pConn.Type == HT_CONN {
-			pConn.params.ErrStr = []byte(fmt.Sprintf("[EC052]Error invalis param type %d", param_type))
-		} else {
-			pParams.ErrStr = []byte(fmt.Sprintf("[EC052]Error invalis param type %d", param_type))
-		}
-		return -52
-	}
-	return 0
-}
-
-func xgSockBindParamByNameSub(pParams *XGCSParam) {
-	if pParams.ParamNum == 0 { //优先考虑 参数不足128个时的情况
-		pParams.PResourceNum = 128
-		pParams.ValueP = make([]byte, 128)
-		pParams.VType = make([]uint32, 128)
-		pParams.VParamSize = make([]uint32, 128)
-		//pParams.VDbType = make([][]int, 128)
-		pParams.VActuallenp = make([][]int, 128)
-		pParams.VParamNo = make([]uint32, 128)
-		pParams.VInOut = make([]int, 128)
-		pParams.VParamName = nil
-	}
-}

+ 143 - 158
xugu/xugu_parse.go

@@ -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
 }

+ 107 - 100
xugu/xugu_prepare.go

@@ -1,115 +1,122 @@
 package xugu
 
 import (
-	"errors"
 	"fmt"
 )
 
 const RETURN_PREPARE_SELECT = 19665
 
-func xgCmdPrepare(pconn *xuguConn, cmd_sql string, prepareName *string) (int, error) {
-	fmt.Println("\n>>>>>xgCmdPrepare")
-	sqlRet := fmt.Sprintf("PREPARE %s AS %s", *prepareName, cmd_sql)
+func xuguPrepare(pConn *xuguConn, cmd_sql string, prepareName string) error {
+	fmt.Println("\n ---xuguPrepare")
+	sqlRet := fmt.Sprintf("PREPARE %s AS %s", prepareName, cmd_sql)
 	//上锁
-	//lockConnect(pconn)
-	pconn.mu.Lock()
-	SockSendCommand0(pconn, sqlRet)
-	var ch byte
-	var ret int
-	for {
-		recvRet, err := rhRecvChar(pconn, &ch)
-		if err != nil {
-			return 0, err
-		}
-		if !recvRet {
-			pconn.mu.Unlock()
-			return -4, errors.New("XG_NET_ERROR")
-		}
-		//A: SelectResult A在协议里为select返回
-		if ch == 'A' {
-			// pres := Result{}
-			// pres.Type = HT_RS
-			// ret, err = recvFiledsInfo(pconn, &pres)
-			// if err != nil {
-			// 	return ret, err
-			// }
-			// pconn.presPrepareCata = &pres
-			ret = RETURN_PREPARE_SELECT
-			continue
-		} else if ch == '$' {
-			var params XGCSParam
-			params.Type = HT_PARAMS
-			params.ImpExpType = 2
-			recvParamsInfo2(pconn, &params)
-			pconn.params = &params
-			continue
-		} else if ch == 'K' {
-			pconn.havePrepare = 1
-		} else {
-			var errStr []byte
-			ret, err = rhRecvStr(pconn, &errStr)
-			if ret < 0 || err != nil {
-				pconn.mu.Unlock()
-				return ret, err
-			}
-			pconn.errStr = errStr
-			ret = XG_ERROR
-			rhRecvChar(pconn, &ch)
-			if ch != 'K' {
-				pconn.bkChar = ch
-				continue
-			}
-		}
-		break
+	//lockConnect(pConn)
+	//pConn.mu.Lock()
+	sockSendPutStatement(pConn, []byte(sqlRet), nil, 0)
+	XGC_Execute(pConn)
+
+	//接收服务器消息返回
+	// pConn.conn.Read(pConn.readBuff.buf)
+	// _, err := parseMsg(&pConn.readBuff, pConn)
+	_, err := xuguSockRecvMsg(pConn)
+	if err != nil {
+		fmt.Println("xuguPrepare parseMsg(&pConn.readBuff, pConn)")
+		return err
 	}
-	pconn.mu.Unlock()
-	return ret, nil
-}
-func xgCmdUnprepare(pConn *xuguConn, prepareName string) int {
-	fmt.Println("\n>>>>>xgCmdUnprepare")
-	var ch byte
-	var err error
-	ret := XG_OK
 
-	sql := fmt.Sprintf("DEALLOCATE %s ", prepareName)
-	pConn.mu.Lock()
-	SockSendCommand0(pConn, sql)
-	boolRet, err := rhRecvChar(pConn, &ch)
-	fmt.Println("rhRecvChar => ch ", ch)
-	if boolRet || err != nil {
-		ret = XG_NET_ERROR
-	} else if ch == 'K' {
-		pConn.havePrepare = 0
-	} else {
-		pConn.havePrepare = 0
-		var errStre []byte
-		ret, err = rhRecvStr(pConn, &errStre)
-		if err != nil || ret < 0 {
-			pConn.mu.Unlock()
-			return ret
-		}
+	fmt.Println("Message from server:", pConn.readBuff.buf[pConn.readBuff.idx:])
+	fmt.Println("Message from server:", string(pConn.readBuff.buf[pConn.readBuff.idx:]))
 
-		rhRecvChar(pConn, &ch)
-		ret = XG_ERROR
-	}
-	pConn.mu.Unlock()
-	return 0
+	fmt.Println("\n ---xuguPrepare end")
+	return nil
 }
 
-// execute for prepare2
-/* XGC_Execute2 综合执行文件 与 prepare2配合使用
-* p_conn 连接句柄
-* prepare_name 准备的prepare, 如果 prepare2(conn,NULL)  那么这里就是执行 XGC_Execute2(p_conn,NULL,NULL,&p_result)
-* servercursor_name  ,生成的服务器端游标, 如果 prepare2(conn,prepare_name) , 那么这里就是执行 XGC_Execute2(p_conn,prepare_name,servercursor_name,NULL)
-* p_res 结果集指针, 其中 servercursor_name 与 pres 不同时并存
- */
-func XGC_Execute(pConn *xuguConn, sql string) int {
-	fmt.Println("\n ---XGC_Execute")
-	//发送没有参数的sql
-	SockSendCommand0(pConn, sql)
-	return 0
-}
+// func xgCmdPrepare(pConn *xuguConn, cmd_sql string, prepareName *string) (int, error) {
+// 	fmt.Println("\n>>>>>xgCmdPrepare")
+// 	sqlRet := fmt.Sprintf("PREPARE %s AS %s", *prepareName, cmd_sql)
+// 	//上锁
+// 	//lockConnect(pConn)
+// 	pConn.mu.Lock()
+// 	SockSendCommand0(pConn, sqlRet)
+// 	var ch byte
+// 	var ret int
+// 	for {
+// 		recvRet, err := rhRecvChar(pConn, &ch)
+// 		if err != nil {
+// 			return 0, err
+// 		}
+// 		if !recvRet {
+// 			pConn.mu.Unlock()
+// 			return -4, errors.New("XG_NET_ERROR")
+// 		}
+// 		//A: SelectResult A在协议里为select返回
+// 		if ch == 'A' {
+// 			// pres := Result{}
+// 			// pres.Type = HT_RS
+// 			// ret, err = recvFiledsInfo(pConn, &pres)
+// 			// if err != nil {
+// 			// 	return ret, err
+// 			// }
+// 			// pConn.presPrepareCata = &pres
+// 			ret = RETURN_PREPARE_SELECT
+// 			continue
+// 		} else if ch == '$' {
+// 			var params XGCSParam
+// 			params.Type = HT_PARAMS
+// 			params.ImpExpType = 2
+// 			recvParamsInfo2(pConn, &params)
+// 			pConn.params = &params
+// 			continue
+// 		} else if ch == 'K' {
+// 			pConn.havePrepare = 1
+// 		} else {
+// 			var errStr []byte
+// 			ret, err = rhRecvStr(pConn, &errStr)
+// 			if ret < 0 || err != nil {
+// 				pConn.mu.Unlock()
+// 				return ret, err
+// 			}
+// 			pConn.errStr = errStr
+// 			ret = XG_ERROR
+// 			rhRecvChar(pConn, &ch)
+// 			if ch != 'K' {
+// 				pConn.bkChar = ch
+// 				continue
+// 			}
+// 		}
+// 		break
+// 	}
+// 	pConn.mu.Unlock()
+// 	return ret, nil
+// }
 
-func send_params(p_conn *xuguConn, p_params *XGCSParam) {
-	fmt.Println("--- send_params(p_conn *xuguConn, p_params *XGCSParam)")
-}
+// func xgCmdUnprepare(pConn *xuguConn, prepareName string) int {
+// 	fmt.Println("\n>>>>>xgCmdUnprepare")
+// 	var ch byte
+// 	var err error
+// 	ret := XG_OK
+
+// 	sql := fmt.Sprintf("DEALLOCATE %s ", prepareName)
+// 	pConn.mu.Lock()
+// 	SockSendCommand0(pConn, sql)
+// 	boolRet, err := rhRecvChar(pConn, &ch)
+// 	fmt.Println("rhRecvChar => ch ", ch)
+// 	if boolRet || err != nil {
+// 		ret = XG_NET_ERROR
+// 	} else if ch == 'K' {
+// 		pConn.havePrepare = 0
+// 	} else {
+// 		pConn.havePrepare = 0
+// 		var errStre []byte
+// 		ret, err = rhRecvStr(pConn, &errStre)
+// 		if err != nil || ret < 0 {
+// 			pConn.mu.Unlock()
+// 			return ret
+// 		}
+
+// 		rhRecvChar(pConn, &ch)
+// 		ret = XG_ERROR
+// 	}
+// 	pConn.mu.Unlock()
+// 	return 0
+// }

+ 0 - 52
xugu/xugu_result.go

@@ -30,55 +30,3 @@ func (self *xuguResult) RowsAffected() (int64, error) {
 	fmt.Println(">>>>>(self *xugusqlResult) RowsAffected()")
 	return self.affectedRows, nil
 }
-
-// type FieldInfo struct {
-// 	TabName string // 基表名
-// 	Name    string // 列名
-// 	Alias   string // 别名
-// 	TypeID  uint32 // 类型 ID
-// 	CTypeID uint32 // ODBC 的 SQL_C_XXX 类型
-// 	Modi    uint32 // 列修改集合
-// 	Flags   uint32 // 列标志,用于是否可为空,是否为主键等
-// 	Offset  uint32 // 列数据偏移量
-// }
-
-// type RhRow struct {
-// 	FieldNum int16    // 字段数量
-// 	State    int16    // 状态
-// 	Mbmk     [20]byte // 标记
-// 	RowData  [4]byte  // 行数据(长度不固定)
-// }
-
-// type Block struct {
-// 	Next     *Block // 下一个块指针
-// 	BuffSize int    // 缓冲区大小
-// 	Off      int    // 偏移量
-// 	Res      int    // 资源
-// 	BlkNo    int    // 块编号(未使用)
-// 	RowNo    int64  // 行号(未使用)
-// 	Data     []byte // 数据
-// }
-// type RSMemStruct struct {
-// 	Head    *Block // 头部块
-// 	CurBlok *Block // 当前块
-// }
-// type Result struct {
-// 	Type          HANDLE_TYPE       // 句柄类型
-// 	State         int32             // 状态
-// 	FieldNum      uint32            // 字段数量
-// 	ColInfos      []FieldInfo       // SELECT 返回的结果集列属性信息
-// 	RowSize       uint32            // 行大小
-// 	ICurrPos      int32             // 当前行位置
-// 	SlotNum       int64             // 槽数量
-// 	Rows          [][][]interface{} // 行数据
-// 	RowNum        int64             // 记录计数器
-// 	CurRec        *RhRow            // 当前记录
-// 	ErrStr        string            // 错误信息字符串
-// 	DbcFlob       *xuguConn         // 数据库连接属性
-// 	IsMultiResult bool              // 是否多结果集
-// 	NextResult    *Result           // 下一个结果集
-// 	PBlokmemls    *RSMemStruct      // 内存块链表,添加于 2019-05-06
-// 	SQLType       int               // SQL 类型:0 未知, 1 插入, 2 更新, 3 删除, 4 查询, 5 其他, 6 创建, 7 修改, 8 开始, 9 声明, 10 设置
-// 	EffectNum     int               // 更新、删除类型的影响行数
-// 	InsertBmk     [32]byte          // 插入类型的标记
-// }

+ 11 - 2
xugu/xugu_rows.go

@@ -8,6 +8,7 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
+	"time"
 )
 
 // type Row struct {
@@ -60,13 +61,21 @@ func (row *xuguRows) Next(dest []driver.Value) error {
 		case fieldType_DATE:
 
 		case fieldType_BINARY,
-			fieldType_CLOB, fieldType_BLOB:
+			fieldType_CLOB,
+			fieldType_BLOB:
+			fmt.Println("这是 fieldType_BINARY")
+			dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
 
 		case fieldType_TIME,
 			fieldType_TIME_TZ:
+			tv, _ := time.Parse("15:04:05", string(row.results.Values[j][row.results.rowIdx].Col_Data))
+			dest[j] = tv
 
 		case fieldType_DATETIME,
 			fieldType_DATETIME_TZ:
+			tv, _ := time.Parse("2006-01-02 15:04:05", string(row.results.Values[j][row.results.rowIdx].Col_Data))
+			dest[j] = tv
+
 		case fieldType_I1:
 			dest[j] = int8(row.results.Values[j][row.results.rowIdx].Col_Data[0])
 		case fieldType_I4:
@@ -105,7 +114,7 @@ func (row *xuguRows) Columns() []string {
 
 	for i, v := range row.results.Fields {
 		columns = append(columns, v.FieldName)
-		fmt.Printf("append(columns, v.FieldName) 个数%d ,%s", i+1, columns[i])
+		fmt.Printf("append(columns, v.FieldName) 个数%d ,v: %s\n", i+1, columns[i])
 	}
 
 	// fmt.Println(" -columns len  ", len(columns))

+ 109 - 31
xugu/xugu_sock.go

@@ -18,54 +18,132 @@ func xgSockOpenConn(ctx context.Context, pConn *xuguConn) error {
 	}
 	fmt.Println("数据已发送:", dsnMessage)
 
-	buffer := make([]byte, 1024)
+	buffer := make([]byte, 1)
 	n, err := pConn.conn.Read(buffer)
 	if err != nil {
 
 		return errors.New("conn 接收数据库连接相应失败:")
 	}
+
 	fmt.Println("读取数据库服务返回:", string(buffer[:n]))
 	//SockSendCommand0(pConn, "set schema SYSTEM")
 	return nil
 }
 
-func xgSockPrepare(pConn *xuguConn, sql string, prepareName *string) (int, error) {
-	fmt.Println(">>>>>xgSockPrepare")
+// func xgSockPrepare(pConn *xuguConn, sql string, prepareName *string) (int, error) {
+// 	fmt.Println(">>>>>xgSockPrepare")
 
-	if "" == *prepareName {
-		ret := 0
-		//p_params := &conn.params
-		if pConn.havePrepare != 0 {
-			ret = xgCmdUnprepare(pConn, pConn.prepareName)
-			if ret < 0 {
-				return ret, errors.New("XG_ERROR")
-			}
-			pConn.prepareName = ""
+// 	if "" == *prepareName {
+// 		ret := 0
+// 		//p_params := &conn.params
+// 		if pConn.havePrepare != 0 {
+// 			ret = xgCmdUnprepare(pConn, pConn.prepareName)
+// 			if ret < 0 {
+// 				return ret, errors.New("XG_ERROR")
+// 			}
+// 			pConn.prepareName = ""
 
-			pConn.prepareName = fmt.Sprintf(pConn.prepareName+"STC%d", pConn.prepareNo)
-			ret, err := xgCmdPrepare(pConn, sql, &pConn.prepareName)
-			if err != nil {
-				return ret, err
-			}
-		}
-		return ret, errors.New("xgSockPrepare_ERROR")
-	}
+// 			pConn.prepareName = fmt.Sprintf(pConn.prepareName+"STC%d", pConn.prepareNo)
+// 			ret, err := xgCmdPrepare(pConn, sql, &pConn.prepareName)
+// 			if err != nil {
+// 				return ret, err
+// 			}
+// 		}
+// 		return ret, errors.New("xgSockPrepare_ERROR")
+// 	}
 
-	ret := 0
+// 	ret := 0
 
-	//	XGCSParam* p_params= pconn->params;
-	old_p := pConn.havePrepare
-	//	char* sql=strdup(cmd_sql);
+// 	//	XGCSParam* p_params= pconn->params;
+// 	old_p := pConn.havePrepare
+// 	//	char* sql=strdup(cmd_sql);
 
-	*prepareName = fmt.Sprintf("STC%d", pConn.prepareNo)
-	pConn.prepareNo++ // 递增 prepare_no 的值
+// 	*prepareName = fmt.Sprintf("STC%d", pConn.prepareNo)
+// 	pConn.prepareNo++ // 递增 prepare_no 的值
 
-	ret, err := xgCmdPrepare(pConn, sql, &pConn.prepareName)
-	if err != nil {
-		return 0, err
+// 	ret, err := xgCmdPrepare(pConn, sql, &pConn.prepareName)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+// 	pConn.havePrepare = old_p // this keeped by prepare_name
+
+// 	return ret, nil
+
+// }
+
+func parseMsg(readBuf *buffer, pConn *xuguConn) (rs *xuguResult, err error) {
+	result := &xuguResult{
+		affectedRows: 0,
+		insertId:     0,
 	}
-	pConn.havePrepare = old_p // this keeped by prepare_name
 
-	return ret, nil
+	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
+			return result, nil
+		case '$':
+			readBuf.idx++
+			fmt.Println("消息类型为$")
+			parseFormArgDescri(readBuf)
+		case 'A':
+			readBuf.idx++
+			fmt.Println("消息类型为A")
+			parseSelectResult(readBuf)
+		case 'I':
+			readBuf.idx++
+			fmt.Println("消息类型为I")
+			parseInsertResult(readBuf)
+		case 'U':
+			fmt.Println("消息类型为U")
+			readBuf.idx++
+			parseUpdateResult(readBuf)
+		case 'D':
+			fmt.Println("消息类型为D")
+			readBuf.idx++
+			parseDeleteResult(readBuf)
+		case 'E':
+			fmt.Println("消息类型为E")
+			readBuf.idx++
+			pErr, err := parseErrInfo(readBuf)
+			if err != nil {
+				return nil, err
+			}
 
+			// fmt.Println("E ReadBuf : ", readBuf.buf[readBuf.idx:])
+			// fmt.Println("E ReadBuf string: ", string(readBuf.buf[readBuf.idx:]))
+			pConn.errStr = pErr.ErrStr
+			// char := readBuf.peekChar()
+			// fmt.Println("Exec 内的 peekChar: ", char)
+		case 'W':
+			fmt.Println("消息类型为W")
+			readBuf.idx++
+			parseWarnInfo(readBuf)
+		case 'M':
+			fmt.Println("消息类型为M")
+			readBuf.idx++
+			parseMessage(readBuf)
+		default:
+			fmt.Println("消息类型为其他")
+			return nil, errors.New("parseMsg: unknown message type")
+		}
+
+	}
+}
+
+func xuguSockRecvMsg(pConn *xuguConn) (rs *xuguResult, err error) {
+	pConn.conn.Read(pConn.readBuff.buf)
+	fmt.Println("pConn.readBuff.buf ::", pConn.readBuff.buf, string(pConn.readBuff.buf))
+	rs, err = parseMsg(&pConn.readBuff, pConn)
+	if err != nil {
+		fmt.Println("xuguPrepare parseMsg(&pConn.readBuff, pConn)")
+		return nil, err
+	}
+	return rs, nil
 }

+ 0 - 132
xugu/xugu_sock_recv2.go

@@ -1,132 +0,0 @@
-package xugu
-
-import (
-	"bufio"
-)
-
-// ----------------------------------------------------------------------------------------------------
-type SrvResponse struct {
-	FormArgDescri []*FormArgDescri
-	SelectResult  []*SelectResult
-	InsertResult  []*InsertResult
-	UpdateResult  []*UpdateResult
-	DeleteResult  []*DeleteResult
-	ProcRet       []*ProcRet
-	OutParamRet   []*OutParamRet
-	ErrInfo       []*ErrInfo
-	WarnInfo      []*WarnInfo
-	Message       []*Message
-}
-
-
-
-// func parseResponse(conn net.Conn) (*SrvResponse, error) {
-// 	response := &SrvResponse{}
-// 	reader := bufio.NewReader(conn)
-
-// 	for {
-// 		msgType, err := reader.ReadByte()
-// 		if err != nil {
-// 			return nil, err
-// 		}
-
-// 		switch msgType {
-// 		case '$':
-// 			argDescri, err := parseFormArgDescri(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.FormArgDescri = append(response.FormArgDescri, argDescri)
-
-// 		case 'I':
-// 			insertResult, err := parseInsertResult(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.InsertResult = append(response.InsertResult, insertResult)
-// 		case 'U':
-// 			updateResult, err := parseUpdateResult(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.UpdateResult = append(response.UpdateResult, updateResult)
-// 		case 'D':
-// 			deleteResult, err := parseDeleteResult(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.DeleteResult = append(response.DeleteResult, deleteResult)
-// 		case 'O':
-// 			procRet, err := parseProcRet(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.ProcRet = append(response.ProcRet, procRet)
-// 		case 'P':
-// 			outParamRet, err := parseOutParamRet(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.OutParamRet = append(response.OutParamRet, outParamRet)
-// 		case 'E':
-// 			errInfo, err := parseErrInfo(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.ErrInfo = append(response.ErrInfo, errInfo)
-// 		case 'W':
-// 			warnInfo, err := parseWarnInfo(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.WarnInfo = append(response.WarnInfo, warnInfo)
-// 		case 'M':
-// 			message, err := parseMessage(reader)
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			response.Message = append(response.Message, message)
-// 		case 'K':
-// 			return response, nil
-// 		default:
-// 			return nil, fmt.Errorf("未知的消息类型: %v", msgType)
-// 		}
-// 	}
-// }
-
-// 解析函数的实现,例如 parseFormArgDescri 等
-
-
-func readString(reader *bufio.Reader, length int) (string, error) {
-	bytes := make([]byte, length)
-	_, err := reader.Read(bytes)
-	return string(bytes), err
-}
-
-func parseFieldDescri(reader *bufio.Reader) (FieldDescri, error) {
-	fieldDescri := FieldDescri{}
-	var err error
-
-	fieldDescri.FieldNameLen, err = readInt32(reader)
-	if err != nil {
-		return fieldDescri, err
-	}
-	fieldDescri.FieldName, err = readString(reader, fieldDescri.FieldNameLen)
-	if err != nil {
-		return fieldDescri, err
-	}
-	// fieldDescri.FieldType, err = fieldType(reader)
-	// if err != nil {
-	// 	return fieldDescri, err
-	// }
-	fieldDescri.FieldPreciScale, err = readInt32(reader)
-	if err != nil {
-		return fieldDescri, err
-	}
-	fieldDescri.FieldFlag, err = readInt32(reader)
-	if err != nil {
-		return fieldDescri, err
-	}
-
-	return fieldDescri, nil
-}

+ 107 - 27
xugu/xugu_sock_send.go

@@ -36,41 +36,111 @@ func SockSendCommandN(pConn *xuguConn, sql string, num int) (int, error) {
 	return ret, nil
 }
 
-func SockSendCommand0(pConn *xuguConn, sql string) (int, error) {
-	cmdLen := len(sql)
-	//发送问号字符 ?
-	ret, err := RhSend(pConn, []byte("?"), cmdLen)
-	if err != nil {
-		return 0, err
+// func SockSendCommand0(pConn *xuguConn, sql string) (int, error) {
+// 	cmdLen := len(sql)
+// 	//发送问号字符 ?
+// 	ret, err := RhSend(pConn, []byte("?"), cmdLen)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+// 	// Comand_Len
+// 	lengthInt32 := uint32(len(sql))
+// 	ret, err = rhSendInt32(pConn, lengthInt32)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+// 	//  Comand_str
+// 	ret, err = RhSend(pConn, []byte(sql), cmdLen+1)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+
+// 	data := make([]byte, 1)
+// 	ret, err = RhSend(pConn, data, 1)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+
+// 	// Param_num
+// 	ret, err = rhSendInt32(pConn, 0)
+// 	if err != nil {
+// 		return 0, err
+// 	}
+// 	fmt.Println("SockSendCommand0 msg", pConn.sendBuff.String())
+
+// 	RhFlush(pConn)
+
+// 	return ret, nil
+// }
+
+func sockSendPutStatement(pConn *xuguConn, sql []byte, values *[]xuguValue, paramCount int) {
+	if pConn.sendBuff.Len() > 0 {
+		//将缓冲区重置为空
+		pConn.sendBuff.Reset()
 	}
+	// ?
+	pConn.sendBuff.Write([]byte("?"))
 	// Comand_Len
-	lengthInt32 := uint32(len(sql))
-	ret, err = rhSendInt32(pConn, lengthInt32)
-	if err != nil {
-		return 0, err
-	}
-	//  Comand_str
-	ret, err = RhSend(pConn, []byte(sql), cmdLen+1)
-	if err != nil {
-		return 0, err
-	}
+	sqlLength := uint32(len(sql))
+	var networkBytes [4]byte
+	binary.BigEndian.PutUint32(networkBytes[:], sqlLength)
+	pConn.sendBuff.Write(networkBytes[:])
 
-	data := make([]byte, 1)
-	ret, err = RhSend(pConn, data, 1)
-	if err != nil {
-		return 0, err
-	}
+	//  Comand_str
+	pConn.sendBuff.Write(sql)
+	//'0' 结束符
+	binary.BigEndian.PutUint32(networkBytes[:], 0)
+	pConn.sendBuff.Write([]byte{0})
 
 	// Param_num
-	ret, err = rhSendInt32(pConn, 0)
-	if err != nil {
-		return 0, err
+	if paramCount > 0 {
+		fmt.Println("paramCount> 0: ", paramCount)
+		binary.BigEndian.PutUint32(networkBytes[:], uint32(paramCount))
+		pConn.sendBuff.Write(networkBytes[:])
+	} else {
+		binary.BigEndian.PutUint32(networkBytes[:], 0)
+		pConn.sendBuff.Write(networkBytes[:])
 	}
-	fmt.Println("SockSendCommand0 msg", pConn.sendBuff.String())
 
-	RhFlush(pConn)
+	if values != nil {
+		fmt.Println("values 不为空")
+		//	Param_num   { Param_name_len Param_name Param_INOUT Param_DType Param_Data_Len Param_Data }
+		for _, value := range *values {
+			//Param_name_len
+			var Param_name_len [2]byte
+			binary.BigEndian.PutUint16(Param_name_len[:], uint16(len(value.paramName)))
+			pConn.sendBuff.Write(Param_name_len[:])
+			fmt.Println("Param_name_len sendBuff ", pConn.sendBuff.Bytes())
+			//Param_name
+			if value.paramName == nil {
+				//pConn.sendBuff.Write([]byte{0})
+			} else {
+				pConn.sendBuff.Write(value.paramName[:])
+				fmt.Println("Param_name sendBuff ", pConn.sendBuff.Bytes())
+			}
 
-	return ret, nil
+			//Param_INOUT
+			Param_INOUT := [2]byte{0x1}
+			pConn.sendBuff.Write(reverseBytes(Param_INOUT[:]))
+			fmt.Println("Param_INOUT sendBuff ", pConn.sendBuff.Bytes())
+			//Param_DType
+			var Param_DType [2]byte
+			binary.BigEndian.PutUint16(Param_DType[:], uint16(value.types))
+			pConn.sendBuff.Write(Param_DType[:])
+			fmt.Println("Param_DType sendBuff ", pConn.sendBuff.Bytes())
+			//Param_Data_Len
+			var Param_Data_Len [4]byte
+			binary.BigEndian.PutUint32(Param_Data_Len[:], uint32(value.valueLength))
+			pConn.sendBuff.Write(Param_Data_Len[:])
+			fmt.Println("Param_Data_Len sendBuff ", pConn.sendBuff.Bytes())
+			//Param_Data
+			pConn.sendBuff.Write([]byte(value.value))
+			fmt.Println("Param_Data sendBuff ", pConn.sendBuff.Bytes())
+		}
+
+	}
+	fmt.Println("SockSendPutStatement msg", pConn.sendBuff.String())
+	fmt.Println("SockSendPutStatement msg", pConn.sendBuff.Bytes())
 }
 
 // RhSend Go 版本的 rh_send 函数
@@ -167,3 +237,13 @@ func RhFlush(pConn *xuguConn) (int, error) {
 	}
 	return 0, nil
 }
+
+func XGC_Execute(pConn *xuguConn) int {
+	fmt.Println("\n ---XGC_Execute")
+	//发送没有参数的sql
+	//SockSendCommand0(pConn, sql)
+	//sockSendPutStatement(pConn, []byte(sql), values)
+	pConn.conn.Write(pConn.sendBuff.Bytes())
+	fmt.Println("\n ---XGC_Execute end")
+	return 0
+}

+ 84 - 60
xugu/xugu_stmt.go

@@ -4,7 +4,6 @@ import (
 	"database/sql/driver"
 	"errors"
 	"fmt"
-	"unsafe"
 )
 
 type xuguStmt struct {
@@ -25,11 +24,11 @@ type xuguStmt struct {
 	curname []byte
 
 	// 执行的 SQL 语句中的参数数量
-	param_count int
-	mysql       string
+	paramCount int
+	mysql      string
 
-	// 上下文结果集句柄指针
-	result unsafe.Pointer
+	//需替换的参数字段信息
+	parser *xuguParse
 }
 
 /* Collect error information from the database server */
@@ -67,63 +66,87 @@ func (stmt *xuguStmt) NumInput() int {
 
 func (stmt *xuguStmt) Exec(args []driver.Value) (driver.Result, error) {
 	fmt.Println(">>>>>>>Exec method called")
-	result := &xuguResult{
-		affectedRows: 0,
-		insertId:     0,
+	fmt.Println("--args ", args)
+	// result := &xuguResult{
+	// 	affectedRows: 0,
+	// 	insertId:     0,
+	// }
+
+	//参数类型绑定
+	if stmt.paramCount > 0 && len(args) > 0 {
+		for pos, param := range args {
+			stmt.parser.assertParamType(param, pos)
+			//fmt.Printf("Field Name: %s, Field Type: %s, Field Value: %v\n", v1, v1, v1)
+		}
+		sockSendPutStatement(stmt.stmt_conn, stmt.prename, &stmt.parser.values, stmt.paramCount)
+		XGC_Execute(stmt.stmt_conn)
+	} else {
+		//最终发送消息给服务器
+		sockSendPutStatement(stmt.stmt_conn, []byte(stmt.mysql), nil, 0)
+		XGC_Execute(stmt.stmt_conn)
 	}
-	//最终发送消息给服务器
-	XGC_Execute(stmt.stmt_conn, stmt.mysql)
+
 	//处理服务器返回
+
 	stmt.stmt_conn.conn.Read(stmt.stmt_conn.readBuff.buf)
-	readBuf := stmt.stmt_conn.readBuff
-	//fmt.Println("Message from server:", (buffer[:n]))
-	fmt.Println("Message from server:", string(stmt.stmt_conn.readBuff.buf))
+	readBuf := &stmt.stmt_conn.readBuff
+	fmt.Println("Message from server EXEC:", readBuf.buf[readBuf.idx:])
+	fmt.Println("Message from server EXEC:", string(stmt.stmt_conn.readBuff.buf))
 
 	//循环读,多条语句执行,会有多条语句返回
 	//读取一字节
-	for {
-		char := readBuf.peekChar()
-		switch char {
-		case 'K':
-			fmt.Println("消息类型为K")
-			//	readBuf.idx++
-			//parseMessage(readBuf)
-			return result, nil
-		case '$':
-			readBuf.idx++
-			fmt.Println("消息类型为$")
-		case 'I':
-			readBuf.idx++
-			fmt.Println("消息类型为I")
-			parseInsertResult(readBuf)
-		case 'U':
-			fmt.Println("消息类型为U")
-			readBuf.idx++
-			parseUpdateResult(readBuf)
-		case 'D':
-			fmt.Println("消息类型为D")
-			readBuf.idx++
-			parseDeleteResult(readBuf)
-		case 'E':
-			fmt.Println("消息类型为E")
-			readBuf.idx++
-			parseErrInfo(readBuf)
-			fmt.Println("E ReadBuf : ", readBuf.buf[readBuf.idx:], string(readBuf.buf[readBuf.idx:]))
-			fmt.Println("E ReadBuf string: ", string(readBuf.buf[readBuf.idx:]))
-
-		case 'W':
-			fmt.Println("消息类型为W")
-			readBuf.idx++
-			parseWarnInfo(readBuf)
-		case 'M':
-			fmt.Println("消息类型为M")
-			readBuf.idx++
-			parseMessage(readBuf)
-		}
-
-		//return nil, errors.New("Exec not implemented")
-
+	rs, err := parseMsg(readBuf, stmt.stmt_conn)
+	if err != nil {
+		return nil, err
 	}
+	return rs, nil
+
+	// for {
+	// 	char := readBuf.peekChar()
+	// 	//fmt.Println("Exec 内的 peekChar: ", char)
+	// 	switch char {
+	// 	case 'K':
+	// 		fmt.Println("消息类型为K")
+	// 		return result, nil
+	// 	case '$':
+	// 		readBuf.idx++
+	// 		fmt.Println("消息类型为$")
+	// 		parseFormArgDescri(readBuf)
+	// 	case 'I':
+	// 		readBuf.idx++
+	// 		fmt.Println("消息类型为I")
+	// 		parseInsertResult(readBuf)
+	// 	case 'U':
+	// 		fmt.Println("消息类型为U")
+	// 		readBuf.idx++
+	// 		parseUpdateResult(readBuf)
+	// 	case 'D':
+	// 		fmt.Println("消息类型为D")
+	// 		readBuf.idx++
+	// 		parseDeleteResult(readBuf)
+	// 	case 'E':
+	// 		fmt.Println("消息类型为E")
+	// 		readBuf.idx++
+	// 		pErr, err := parseErrInfo(readBuf)
+	// 		if err != nil {
+	// 			return nil, err
+	// 		}
+	// 		// fmt.Println("E ReadBuf : ", readBuf.buf[readBuf.idx:])
+	// 		// fmt.Println("E ReadBuf string: ", string(readBuf.buf[readBuf.idx:]))
+	// 		stmt.stmt_conn.errStr = pErr.ErrStr
+	// 		// char := readBuf.peekChar()
+	// 		// fmt.Println("Exec 内的 peekChar: ", char)
+	// 	case 'W':
+	// 		fmt.Println("消息类型为W")
+	// 		readBuf.idx++
+	// 		parseWarnInfo(readBuf)
+	// 	case 'M':
+	// 		fmt.Println("消息类型为M")
+	// 		readBuf.idx++
+	// 		parseMessage(readBuf)
+	// 	}
+	// 	//return nil, errors.New("Exec not implemented")
+	// }
 
 }
 
@@ -153,14 +176,14 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 		}
 
 		//fmt.Printf("len(parser.Val) = %d\n , parser.assertParamCount(stmt.mysql) = %d\n", len(parser.Val), parser.assertParamCount(stmt.mysql))
-		if len(parser.Val) != parser.assertParamCount(stmt.mysql) {
+		if len(parser.values) != parser.assertParamCount(stmt.mysql) {
 			return nil, errors.New("The number of parameters does not match")
 		}
 
 		switch parser.assertBindType(stmt.mysql) {
 		case BIND_PARAM_BY_POS:
 			fmt.Println("--BIND_PARAM_BY_POS")
-			for pos, param := range parser.Val {
+			for pos, param := range parser.values {
 				if !param.islob {
 					fmt.Printf("pos: %d, param %#v \n", pos, param)
 					stmt.mysql = parser.bindParamByPos(stmt.mysql)
@@ -170,7 +193,7 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 		case BIND_PARAM_BY_NAME:
 			fmt.Println("--BIND_PARAM_BY_NAME")
 			parser.assertParamName(stmt.mysql)
-			for pos, param := range parser.Val {
+			for pos, param := range parser.values {
 				if !param.islob {
 					fmt.Println("pos: ", pos, "param: ", param)
 				}
@@ -184,7 +207,8 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 	// }
 
 	//最终发送消息给服务器
-	XGC_Execute(stmt.stmt_conn, stmt.mysql)
+	sockSendPutStatement(stmt.stmt_conn, []byte(stmt.mysql), nil, 0)
+	XGC_Execute(stmt.stmt_conn)
 
 	//----------------处理服务器查询返回
 
@@ -193,7 +217,7 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 	//fmt.Println("Message from server:", (buffer[:n]))
 	fmt.Println("Message from server:", string(stmt.stmt_conn.readBuff.buf))
 	//fmt.Println("\nMessage from server2:", (stmt.stmt_conn.readBuff.buf))
-	results, err := parseSelectResult(stmt.stmt_conn.readBuff)
+	results, err := parseSelectResult(&stmt.stmt_conn.readBuff)
 	if err != nil {
 		fmt.Println("parseSelectResult parseSelectResult err", err.Error())
 		return nil, err

+ 1 - 1
xugu/xugu_test.go

@@ -37,7 +37,7 @@ func GetConn() (xgConn *xuguConn) {
 }
 func TestXugu_GetConnection(t *testing.T) {
 	xgConn := GetConn()
-	SockSendCommand0(xgConn, "select * from gotest")
+	//SockSendCommand0(xgConn, "select * from gotest")
 	///	parseResponse(conn)
 	// 接收服务器的返回消息
 	buffer := make([]byte, 1024)

+ 37 - 0
xugu/xugu_tranx.go

@@ -0,0 +1,37 @@
+package xugu
+
+import "errors"
+
+type xuguTx struct {
+	tconn *xuguConn
+}
+
+func (self *xuguTx) Commit() error {
+	if self.tconn == nil {
+		return errors.New("Invalid connection")
+	}
+	_, err := self.tconn.exec("commit;")
+
+	_, err = self.tconn.exec("set auto_commit on;")
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (self *xuguTx) Rollback() error {
+
+	if self.tconn == nil {
+		return errors.New("Invalid connection")
+	}
+	_, err := self.tconn.exec("rollback;")
+	if err != nil {
+		return err
+	}
+
+	_, err = self.tconn.exec("set auto_commit on;")
+	if err != nil {
+		return err
+	}
+	return err
+}

+ 14 - 0
xugu/xugu_utils.go

@@ -252,3 +252,17 @@ func reverseBytes(b []byte) []byte {
 	}
 	return reversed
 }
+
+// 反转 uint32 类型 的大小端
+func swapEndian(num uint32) uint32 {
+	// 获取每个字节
+	b0 := byte(num & 0xFF)
+	b1 := byte((num >> 8) & 0xFF)
+	b2 := byte((num >> 16) & 0xFF)
+	b3 := byte((num >> 24) & 0xFF)
+
+	// 反转字节顺序并组合成新的 uint32
+	swappedNum := uint32(b0)<<24 | uint32(b1)<<16 | uint32(b2)<<8 | uint32(b3)
+
+	return swappedNum
+}

+ 6 - 5
协议.ini

@@ -51,7 +51,8 @@ http://gitlab2.xugu.com/cyj/xugusql
 
     2.1 客户端发出访问: 
 	
-        QryStream:  '?'  Comand_Len   Comand_str   Param_num   { Param_name_len Param_name  Param_DType Param_Data_Len Param_Data }*
+        QryStream:  '?'  Comand_Len   Comand_str   Param_num   { Param_name_len Param_name Param_INOUT Param_DType Param_Data_Len Param_Data }*
+		?  5 ? STC 1 0 1   type_int 4 1
 		
 	解释:
 		Command_len: 	命令长度(网络序32位整数,计算命令长度时不包括结束符0x0)
@@ -60,13 +61,13 @@ http://gitlab2.xugu.com/cyj/xugusql
 		
 		Param_name_len: 参数名字长度(网络序短整数,若参数无名,则此值为0)
 		Param_name:	参数名(该部分字节数应与Param_name_Len一致)
-		
-		参数输出输入类型
+		Param_INOUT: 参数输出输入类型(网络序16位整数)
 		Param_DType:	参数数据类型号(网络序16位整数)
 		Param_Data_Len:	参数长度(网络序32位整数)
 		Param_Data:	参数数据(该部分字节数应与Param_Data_Len一致)
 		
 		{}*:		表示参数部分可有0至多个参数,其重复的次数取决于Param_num,若Param_num为0,则没有参数需要发送
+ 
  		
 
     2.2 服务器返回:  服务器可返回一组或多组信息,并以字节'K'标识所有信息已传送完毕
@@ -99,8 +100,8 @@ http://gitlab2.xugu.com/cyj/xugusql
 		Arg_Num:	 形参个数(网络序32位整数)
 		Arg_Name_Len:	 形参名长度(网络序32位整数)
 		Arg_Name:	 形参名(字节数与Arg_Name_Len一致)
-		Arg_No:		 形参的序号(网络序32位整数,若prepare语句中使用?号表示参数,则服务器按?号的顺序从1开始为其设定序号)
-		Arg_DType:	 形参的数据类型ID(网络序32位整数)
+		Ar_No:		 形参的序号(网络序32位整数,若prepare语句中使用?号表示参数,则服务器按?号的顺序从1开始为其设定序号)
+		Argg_DType:	 形参的数据类型ID(网络序32位整数)
 		Arg_Preci_Scale: 形参的精度标度(网络序32位整数
 
 		SelectResult:	 查询结果集,包含一组结果集字段描述 以及0至多个行数据