瀏覽代碼

完善buf

GTong 10 月之前
父節點
當前提交
8dae166ad2
共有 20 個文件被更改,包括 698 次插入199 次删除
  1. 3 0
      .gitignore
  2. 8 0
      go.mod
  3. 99 2
      main.go
  4. 二進制
      test/a.jpg
  5. 二進制
      test/b.jpg
  6. 二進制
      test/c.jpg
  7. 49 0
      test/create_table_test.go
  8. 二進制
      test/d.jpg
  9. 35 0
      test/dbexec_test.go
  10. 37 0
      test/dbquery_test.go
  11. 61 0
      test/lob_test.go
  12. 37 14
      xugu/xugu_buffer.go
  13. 12 6
      xugu/xugu_conn.go
  14. 1 1
      xugu/xugu_connector.go
  15. 1 1
      xugu/xugu_define.go
  16. 160 136
      xugu/xugu_parse.go
  17. 156 0
      xugu/xugu_parse_time.go
  18. 24 14
      xugu/xugu_rows.go
  19. 10 24
      xugu/xugu_sock.go
  20. 5 1
      xugu/xugu_stmt.go

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+xugusql_driver/
+go.mod
+go.sum

+ 8 - 0
go.mod

@@ -1,3 +1,11 @@
 module xugu_go_driver
 
 go 1.22.2
+
+require gorm.io/gorm v1.25.11
+
+require (
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	golang.org/x/text v0.14.0 // indirect
+)

+ 99 - 2
main.go

@@ -2,12 +2,15 @@ package main
 
 import (
 	"database/sql"
+	"fmt"
 	"log"
+	"os"
+	"sync"
 	_ "xugu_go_driver/xugu"
 )
 
 func main() {
-	db, err := sql.Open("xugusql", "IP=10.28.20.101;DB=SYSTEM;User=SYSDBA;PWD=SYSDBA;Port=5190;AUTO_COMMIT=on;CHAR_SET=UTF8")
+	db, err := sql.Open("xugusql", "IP=192.168.2.216;DB=SYSTEM;User=SYSDBA;PWD=SYSDBA;Port=15138;AUTO_COMMIT=on;CHAR_SET=UTF8")
 	if err != nil {
 		log.Fatal("err ", err)
 	}
@@ -88,5 +91,99 @@ func main() {
 	// }
 	// rows.Close()
 
-	db.Exec("set auto_commit on;")
+	//	db.Exec("set auto_commit on;")
+
+	// rows, err := db.Query("select * from gotab2;")
+	// if err != nil {
+	// 	fmt.Printf("[ERROR] %s\n", err.Error())
+	// 	return
+	// }
+
+	// column, err := rows.Columns()
+	// if err != nil {
+	// 	fmt.Printf("[ERROR] %s\n", err.Error())
+	// 	return
+	// }
+	// rows_value := make([]interface{}, len(column))
+	// for key, _ := range rows_value {
+	// 	dest := make([]byte, 216)
+	// 	rows_value[key] = &dest
+	// }
+
+	// for rows.Next() {
+	// 	rows.Scan(rows_value...)
+
+	// 	for _, v := range rows_value {
+	// 		fmt.Printf("结果: %s\t", string(*(v.(*[]byte))))
+	// 	}
+	// 	fmt.Printf("\n")
+	// }
+
+	// rows.Close()
+	// db.Close()
+	// 打开文件以写入
+	file, err := os.OpenFile("output.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
+	if err != nil {
+		log.Fatalf("无法打开文件: %v", err)
+	}
+	defer file.Close()
+
+	// 创建一个新的日志记录器,将输出写入文件
+	logger := log.New(file, "", log.LstdFlags)
+	var wg sync.WaitGroup
+	const numGoroutines = 10000
+
+	for i := 0; i < numGoroutines; i++ {
+		wg.Add(1)
+		go func(i int) {
+			defer wg.Done()
+			processQuery(db, i, logger)
+		}(i)
+	}
+
+	wg.Wait()
+	fmt.Println("所有goroutine已完成")
+	defer db.Close()
+}
+
+func processQuery(db *sql.DB, id int, logger *log.Logger) {
+	fmt.Printf("goroutine %d 开始\n", id)
+	//db.Query("select 1 from dual;")
+	rows, err := db.Query("select * from gotab3;")
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		logger.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+	defer rows.Close()
+
+	column, err := rows.Columns()
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		logger.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+
+	rowsValue := make([]interface{}, len(column))
+	for key := range rowsValue {
+		dest := make([]byte, 100000)
+		rowsValue[key] = &dest
+	}
+
+	for rows.Next() {
+		err := rows.Scan(rowsValue...)
+		if err != nil {
+			fmt.Printf("[ERROR] %s\n", err.Error())
+			logger.Printf("[ERROR] %s\n", err.Error())
+			return
+		}
+
+		for _, v := range rowsValue {
+			sss := []byte(*(v.(*[]byte)))
+			v = sss
+		}
+	}
+	//time.Sleep(time.Second * 100)
+	logger.Println("goroutine %d 完成\n", id)
+	fmt.Printf("goroutine %d 完成\n", id)
 }

二進制
test/a.jpg


二進制
test/b.jpg


二進制
test/c.jpg


+ 49 - 0
test/create_table_test.go

@@ -0,0 +1,49 @@
+package test
+
+import (
+	"database/sql"
+	"fmt"
+	"testing"
+	_ "xugu_go_driver/xugu"
+)
+
+var crea = []string{
+
+	"create table gotab3(C1 INT, C2 CLOB, C3 BLOB, C4 BINARY)"}
+
+var db *sql.DB
+
+func init() {
+	var err error
+	db, err = sql.Open("xugusql", "IP=192.168.2.216;"+
+		"DB=SYSTEM;User=SYSDBA;PWD=SYSDBA;"+
+		"Port= 15138;AUTO_COMMIT=on;CHAR_SET=UTF8")
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+	}
+}
+
+func TestCreateTable(t *testing.T) {
+
+	// db, err := sql.Open("xugusql", "IP=10.28.20.101;"+
+	// 	"DB=godb;User=SYSDBA;PWD=SYSDBA;"+
+	// 	"Port=5190;AUTO_COMMIT=on;CHAR_SET=UTF8")
+
+	for _, sql := range crea {
+
+		_, err := db.Exec(sql)
+		if err != nil {
+
+			fmt.Printf("[ERROR] %s\n", err.Error())
+			continue
+		}
+
+		fmt.Printf("%s ... ok\n", sql)
+	}
+
+	err := db.Close()
+	if err != nil {
+
+		fmt.Printf("[ERROR] %s\n", err.Error())
+	}
+}

二進制
test/d.jpg


+ 35 - 0
test/dbexec_test.go

@@ -0,0 +1,35 @@
+package test
+
+import (
+	"fmt"
+	"testing"
+)
+
+var unit_test = "ddl"
+
+var INS = []string{
+	"INSERT INTO gotab1 VALUES(1, 0.27, 0.99);",
+	"INSERT INTO gotab1 VALUES(1, NULL, NULL);",
+	"INSERT INTO gotab2 VALUES(1, 'XuguSQL', '2020-01-01 00:00:00');",
+	"INSERT INTO gotab2 VALUES(1, '', NULL);"}
+
+func TestDbexec(t *testing.T) {
+
+	for _, sql := range INS {
+
+		_, err := db.Exec(sql)
+		if err != nil {
+
+			fmt.Printf("[ERROR] %s\n", err.Error())
+			continue
+		}
+
+		fmt.Printf("%s ... ok\n", sql)
+	}
+
+	err := db.Close()
+	if err != nil {
+
+		fmt.Printf("[ERROR] %s\n", err.Error())
+	}
+}

+ 37 - 0
test/dbquery_test.go

@@ -0,0 +1,37 @@
+package test
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestDBQuery(t *testing.T) {
+	rows, err := db.Query("select * from gotab2;")
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+
+	column, err := rows.Columns()
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+	rows_value := make([]interface{}, len(column))
+	for key, _ := range rows_value {
+		dest := make([]byte, 216)
+		rows_value[key] = &dest
+	}
+
+	for rows.Next() {
+		rows.Scan(rows_value...)
+
+		for _, v := range rows_value {
+			fmt.Printf("结果: %s\t", string(*(v.(*[]byte))))
+		}
+		fmt.Printf("\n")
+	}
+
+	rows.Close()
+	db.Close()
+}

+ 61 - 0
test/lob_test.go

@@ -0,0 +1,61 @@
+package test
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"testing"
+)
+
+func TestInsertLob(t *testing.T) {
+	// 打开文件
+	file, err := os.Open("A.jpg")
+	if err != nil {
+		fmt.Println("Error opening file:", err)
+		return
+	}
+	// 确保在函数结束时关闭文件
+	defer file.Close()
+	// 读取文件内容
+	fileContent, err := io.ReadAll(file)
+	if err != nil {
+		fmt.Println("Error reading file:", err)
+		return
+	}
+
+	_, err = db.Exec("INSERT INTO gotab3 VALUES(?,NULL,?,NULL);", 3, fileContent)
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+	}
+}
+
+func TestSelecttLob(t *testing.T) {
+	rows, err := db.Query("select * from gotab3;")
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+
+	column, err := rows.Columns()
+	if err != nil {
+		fmt.Printf("[ERROR] %s\n", err.Error())
+		return
+	}
+	rows_value := make([]interface{}, len(column))
+	for key, _ := range rows_value {
+		dest := make([]byte, 1000000)
+		rows_value[key] = &dest
+	}
+
+	for rows.Next() {
+		rows.Scan(rows_value...)
+
+		for _, v := range rows_value {
+			fmt.Printf("结果: %s\t", string(*(v.(*[]byte))))
+		}
+		fmt.Printf("\n")
+	}
+
+	rows.Close()
+	db.Close()
+}

+ 37 - 14
xugu/xugu_buffer.go

@@ -14,7 +14,7 @@ var (
 type buffer struct {
 	buf     []byte // buf 是一个字节缓冲区,长度和容量相等。
 	conn    net.Conn
-	idx     int
+	idx     int64
 	length  int
 	timeout time.Duration
 }
@@ -30,7 +30,7 @@ func newBuffer(nc net.Conn) buffer {
 // store 存储 buf,这是一个更新的缓冲区,如果合适的话。
 func (b *buffer) store(buf []byte) error {
 	if len(buf) > cap(b.buf) {
-		fmt.Println("大于缓冲区: len(buf) > cap(b.buf)")
+
 		return ErrBusyBuffer
 	}
 	b.buf = buf[:cap(buf)]
@@ -45,36 +45,59 @@ func (b *buffer) peekChar() byte {
 }
 func (b *buffer) reset() {
 	b.idx = 0
+	b.length = 0
 	b.buf = make([]byte, 2048)
 }
 
-// 返回指定字节的切片
-func (b *buffer) readNext(need int, reverse bool) []byte {
+func (b *buffer) readNext(need int, reverse bool) ([]byte, error) {
 	//长度不够返回
-	if len(b.buf[b.idx:]) < need {
-		//调用一次接收服务器消息
-		b.conn.Read(b.buf[b.idx:])
-		offset := b.idx
-		b.idx += need
 
-		return b.buf[offset:b.idx]
+	if len(b.buf[b.idx:b.length]) < need {
+		buffer := make([]byte, need+1)
+		b.buf = append(b.buf[:b.length], buffer...)
+		n, err := b.conn.Read(b.buf[b.length:])
+		if err != nil {
+			// if err == io.EOF {
+
+			// }
+			//	fmt.Println("Error reading from server:", err)
+			return nil, err
+		}
+
+		b.length += n
+
+		for b.length-int(b.idx) < need {
+
+			n, err := b.conn.Read(b.buf[b.length:])
+			if err != nil {
+				// if err == io.EOF {
+				// 	fmt.Println("End of data")
+
+				// }
+				fmt.Println("Error reading from server:", err)
+				return nil, err
+			}
+			//nTmp += n
+			b.length += n
+		}
+
 	}
 
 	offset := b.idx
-	b.idx += need
+	b.idx += int64(need)
 
-	//fmt.Println("readNext: ", b.buf[offset:b.idx])
 	if reverse {
 		//	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))
 
-		return tmp
+		return tmp, nil
 	} else {
 		//	fmt.Println("readNext: 没有转换:", b.buf[offset:b.idx])
 		//	fmt.Println("readNext: 没有转换:", string(b.buf[offset:b.idx]))
-		return b.buf[offset:b.idx]
+
+		return b.buf[offset:b.idx], nil
 	}
 
 }

+ 12 - 6
xugu/xugu_conn.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"context"
 	"database/sql/driver"
+	"encoding/binary"
 	"errors"
 	"fmt"
 	"net"
@@ -51,7 +52,7 @@ type dsnConfig struct {
 func (xgConn *xuguConn) Begin() (driver.Tx, error) {
 	gt("xuguConn.Begin")
 	defer gt("xuguConn.Begin end")
-	return nil, nil
+	return &xuguTx{tconn: xgConn}, nil
 
 }
 
@@ -122,7 +123,7 @@ func (xgConn *xuguConn) Query(sql string,
 
 	switch aR.rt {
 	case selectResult:
-		fmt.Printf("selectResult %#v\n", aR.s)
+
 		rows := &xuguRows{
 			rows_conn: xgConn,
 			results:   aR.s,
@@ -198,7 +199,6 @@ func (xgConn *xuguConn) Prepare(sql string) (driver.Stmt, error) {
 	}
 	stmt.prename = []byte(fmt.Sprintf("? %s", xgConn.prepareName))
 
-	fmt.Println("stmt.prename ", stmt.prename, string(stmt.prename))
 	return stmt, nil
 }
 
@@ -208,7 +208,6 @@ func xuguPrepare(pConn *xuguConn, cmd_sql string, prepareName string) error {
 	prepareName = fmt.Sprintf("%s%d", prepareName, pConn.prepareNo)
 	sqlRet := fmt.Sprintf("PREPARE %s AS %s", prepareName, cmd_sql)
 	pConn.prepareName = prepareName
-	fmt.Println("pConn.prepareName ", pConn.prepareName)
 	pConn.prepareNo++
 	//send msg
 	sockSendPutStatement(pConn, []byte(sqlRet), nil, 0)
@@ -220,8 +219,6 @@ func xuguPrepare(pConn *xuguConn, cmd_sql string, prepareName string) error {
 		return err
 	}
 
-	fmt.Println("Message from server:", pConn.readBuff.buf[pConn.readBuff.idx:])
-	fmt.Println("Message from server:", string(pConn.readBuff.buf[pConn.readBuff.idx:]))
 
 	fmt.Println("\n ---xuguPrepare end")
 
@@ -287,6 +284,10 @@ func (xgConn *xuguConn) Exec(sql string,
 	case warnInfo:
 
 		return nil, errors.New(string(aR.w.WarnStr))
+	case updateResult:
+		return &xuguResult{affectedRows: int64(aR.u.UpdateNum), insertId: int64(0)}, nil
+	case insertResult:
+		return &xuguResult{affectedRows: int64(0), insertId: int64(aR.i.RowidLen)}, nil
 	default:
 		return &xuguResult{
 			affectedRows: int64(0),
@@ -338,6 +339,11 @@ func (xgConn *xuguConn) exec(sql string, args []driver.Value) (driver.Result, er
 	case selectResult:
 
 		return nil, errors.New("exec is Query error")
+	case updateResult:
+		return &xuguResult{affectedRows: int64(aR.u.UpdateNum), insertId: int64(0)}, nil
+	case insertResult:
+
+		return &xuguResult{affectedRows: int64(0), insertId: int64(binary.LittleEndian.Uint64(aR.i.RowidData))}, nil
 	case errInfo:
 
 		return nil, errors.New(string(aR.e.ErrStr))

+ 1 - 1
xugu/xugu_connector.go

@@ -37,7 +37,7 @@ func (conntor *connector) Connect(ctx context.Context) (driver.Conn, error) {
 	xgConn := &xuguConn{conn: nil}
 	xgConn.dsnConfig = dsnConfig
 
-	nd := net.Dialer{Timeout: 5 * time.Second}
+	nd := net.Dialer{Timeout: 50 * time.Second}
 	netConn, err := nd.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", xgConn.IP, xgConn.Port))
 	if err != nil {
 		fmt.Println("tcp Connect error: ", err)

+ 1 - 1
xugu/xugu_define.go

@@ -4,7 +4,7 @@ package xugu
 type msgType byte
 
 const (
-	selectResult msgType = iota + 0x00
+	selectResult msgType = iota + 0x01
 	insertResult
 	updateResult
 	deleteResult

+ 160 - 136
xugu/xugu_parse.go

@@ -202,7 +202,12 @@ func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
 	fmt.Println("--=char: ", string(char), char)
 
 	//Field_Num
-	Field_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	fn, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+
+	Field_Num := binary.LittleEndian.Uint32(fn)
 	data.Field_Num = Field_Num
 	data.rowIdx = 0
 	fmt.Println("Field_Num: ", data.Field_Num)
@@ -213,16 +218,36 @@ func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
 		field := FieldDescri{}
 
 		//Field_Name_Len
-		field.FieldNameLen = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
+		Field_Name_Len, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		field.FieldNameLen = int(binary.LittleEndian.Uint32(Field_Name_Len))
 		fmt.Println("field.FieldNameLen: ", field.FieldNameLen)
+
 		//Field_Name:
-		field.FieldName = string(readBuf.readNext(field.FieldNameLen, false))
+		Field_Name, err := readBuf.readNext(field.FieldNameLen, false)
+		if err != nil {
+			return nil, err
+		}
+		field.FieldName = string(Field_Name)
 		fmt.Println("field.Field_Name: ", field.FieldName)
+
 		//Field_DType:
-		field.FieldType = fieldType(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
+		Field_DType, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		field.FieldType = fieldType(binary.LittleEndian.Uint32(Field_DType))
 		fmt.Println("field.FieldType: ", field.FieldType)
+
 		//Field_Preci_Scale:
-		fieldPreciScale := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+		Field_Preci_Scale, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+
+		fieldPreciScale := binary.LittleEndian.Uint32(Field_Preci_Scale)
 		if int32(fieldPreciScale) <= 0 {
 			field.FieldPreciScale = fieldPreciScaleInfo{
 				scale:    0,
@@ -235,8 +260,13 @@ func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
 			}
 		}
 		fmt.Println("field.FieldPreciScale: ", field.FieldPreciScale)
+
 		//Field_Flag:
-		field.FieldFlag = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+		Field_Flag, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		field.FieldFlag = binary.LittleEndian.Uint32(Field_Flag)
 		fmt.Println("field.FieldFlag: ", field.FieldFlag)
 		data.Fields = append(data.Fields, field)
 	}
@@ -263,15 +293,26 @@ func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
 		for {
 			col := FieldValue{}
 			//获取数据的大小
-			col.Col_len = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-			fmt.Println("数据大小为: ", col.Col_len)
+			Col_len, err := readBuf.readNext(4, true)
+			if err != nil {
+				return nil, err
+			}
+			col.Col_len = binary.LittleEndian.Uint32(Col_len)
+
+			//获取数据的值
+			col.Col_Data, err = readBuf.readNext(int(col.Col_len), false)
+			if err != nil {
+				return nil, err
+			}
 
-			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))
+			// if col.Col_len > 8000 {
+			// 	fmt.Println("数据为: ", col.Col_Data)
+			// }
 			char := readBuf.peekChar()
+
+			//fmt.Println("buf is ", readBuf.buf[readBuf.idx:])
 			//既不是R 也不是K 代表该行还有其他字段内容没有读取完成
 			if char == 'R' {
 				readBuf.idx++
@@ -306,111 +347,19 @@ func parseSelectResult(readBuf *buffer) (*SelectResult, error) {
 
 }
 
-// func parseSelectResult2(readBuf *buffer) (*SelectResult, error) {
-
-// 	data := &SelectResult{}
-// 	char := readBuf.peekChar()
-// 	if char == 'K' {
-// 		return nil, errors.New("parseSelectResult error char is K")
-// 	}
-
-// 	fmt.Println("--=char: ", string(char))
-// 	//Field_Num
-// 	Field_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-// 	data.Field_Num = Field_Num
-// 	//data.rowIdx = 0
-// 	fmt.Println("Field_Num: ", data.Field_Num)
-
-// 	//获取字段信息
-// 	for i := 0; i < int(Field_Num); i++ {
-
-// 		field := FieldDescri{}
-
-// 		//Field_Name_Len
-// 		field.FieldNameLen = int(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
-// 		fmt.Println("field.FieldNameLen: ", field.FieldNameLen)
-// 		//Field_Name:
-// 		field.FieldName = string(readBuf.readNext(field.FieldNameLen, false))
-// 		fmt.Println("field.Field_Name: ", field.FieldName)
-// 		//Field_DType:
-// 		field.FieldType = fieldType(binary.LittleEndian.Uint32(readBuf.readNext(4, true)))
-// 		fmt.Println("field.FieldType: ", field.FieldType)
-// 		//Field_Preci_Scale:
-// 		fieldPreciScale := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-// 		if int32(fieldPreciScale) <= 0 {
-// 			field.FieldPreciScale = fieldPreciScaleInfo{
-// 				scale:    0,
-// 				accuracy: 0,
-// 			}
-// 		} else {
-// 			field.FieldPreciScale = fieldPreciScaleInfo{
-// 				scale:    uint16(fieldPreciScale >> 16),
-// 				accuracy: uint16(fieldPreciScale & 0xFFFF),
-// 			}
-// 		}
-// 		fmt.Println("field.FieldPreciScale: ", field.FieldPreciScale)
-// 		//Field_Flag:
-// 		field.FieldFlag = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-// 		fmt.Println("field.FieldFlag: ", field.FieldFlag)
-// 		data.Fields = append(data.Fields, field)
-// 	}
-
-// 	//获取字段的行值,并判断类型
-// 	// 使用 Peek 方法检查下一个字节是否为'R'或'K'
-// 	fmt.Println("\n\n=========开始获取行数据=================================")
-// 	defer func() {
-// 		fmt.Println("\n\n=========获取行数据结束=================================")
-// 	}()
-
-// 	//data.Values = make([][]FieldValue, 0)
-// 	data.Values = [][]FieldValue
-// 	colIdx := 0
-// 	char = readBuf.peekChar()
-// 	fmt.Println("  --char: ", string(char))
-// 	readBuf.idx++
-// 	if char == 'K' {
-// 		return data, nil
-// 	} else if char == 'R' {
-// 		for {
-// 			col := FieldValue{}
-// 			//获取数据的大小
-// 			col.Col_len = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-// 			fmt.Println("数据大小为: ", col.Col_len)
-
-// 			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()
-// 			//next for
-// 			if char == 'R' {
-// 				readBuf.idx++
-// 				continue
-
-// 				//end parse
-// 			} else if char == 'K' {
-// 				return data, nil
-
-// 			}
-// 			//swich end
-// 			fmt.Println("循环结束")
-// 			fmt.Printf("解析请求 data:%#v\n", data.Fields)
-// 			return data, nil
-// 		} //for end
-// 	} else {
-// 		return data, errors.New("select parse error")
-// 	}
-
-// }
-
 func parseInsertResult(readBuf *buffer) (*InsertResult, error) {
 
 	//Rowid_Len
-	Rowid_Len := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	Rowid_L, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	Rowid_Len := binary.LittleEndian.Uint32(Rowid_L)
 	//Rowid_Data
-	encoded := readBuf.readNext(int(Rowid_Len), false)
+	encoded, err := readBuf.readNext(int(Rowid_Len), false)
+	if err != nil {
+		return nil, err
+	}
 
 	//检测是否结束
 	char := readBuf.peekChar()
@@ -425,34 +374,67 @@ func parseInsertResult(readBuf *buffer) (*InsertResult, error) {
 }
 
 func parseUpdateResult(readBuf *buffer) (*UpdateResult, error) {
-	updateNum := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	updatas, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	updateNum := binary.LittleEndian.Uint32(updatas)
 
 	return &UpdateResult{UpdateNum: updateNum}, nil
 }
 
 func parseDeleteResult(readBuf *buffer) (*DeleteResult, error) {
-	deleteNum := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	deletes, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	deleteNum := binary.LittleEndian.Uint32(deletes)
 
 	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)
+	retDypes, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	retDType := binary.LittleEndian.Uint32(retDypes)
+	retDataLens, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	retDataLen := binary.LittleEndian.Uint32(retDataLens)
+	retData, err := readBuf.readNext(int(retDataLen), false)
+	if err != nil {
+		return nil, err
+	}
 
 	return &ProcRet{RetDType: retDType, RetDataLen: retDataLen, RetData: retData}, nil
 }
 
 func parseOutParamRet(readBuf *buffer) (*OutParamRet, error) {
-	outParamNo := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	outParamNos, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	outParamNo := binary.LittleEndian.Uint32(outParamNos)
 
-	outParamDType := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	outParamDTypes, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	outParamDType := binary.LittleEndian.Uint32(outParamDTypes)
 
-	outParamLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	outParamLens, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	outParamLen := binary.LittleEndian.Uint32(outParamLens)
 
-	outParamData := readBuf.readNext(int(outParamLen), false)
+	outParamData, err := readBuf.readNext(int(outParamLen), false)
+	if err != nil {
+		return nil, err
+	}
 
 	return &OutParamRet{
 		OutParamNo:    outParamNo,
@@ -463,47 +445,89 @@ func parseOutParamRet(readBuf *buffer) (*OutParamRet, error) {
 }
 
 func parseErrInfo(readBuf *buffer) (*ErrInfo, error) {
-	errStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
-
-	errStr := readBuf.readNext(int(errStrLen), false)
+	errStrLens, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	errStrLen := binary.LittleEndian.Uint32(errStrLens)
 
+	errStr, err := readBuf.readNext(int(errStrLen), false)
+	if err != nil {
+		return nil, err
+	}
 	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)
+	warnStrLens, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	warnStrLen := binary.LittleEndian.Uint32(warnStrLens)
 
+	warnStr, err := readBuf.readNext(int(warnStrLen), false)
+	if err != nil {
+		return nil, err
+	}
 	return &WarnInfo{WarnStrLen: warnStrLen, WarnStr: warnStr}, nil
 }
 
 func parseMessage(readBuf *buffer) (*Message, error) {
-	msgStrLen := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	msgStrLens, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	msgStrLen := binary.LittleEndian.Uint32(msgStrLens)
 
-	msgStr := readBuf.readNext(int(msgStrLen), false)
+	msgStr, err := readBuf.readNext(int(msgStrLen), false)
+	if err != nil {
+		return nil, err
+	}
 
 	return &Message{MsgStrLen: msgStrLen, MsgStr: msgStr}, nil
 }
 
 func parseFormArgDescri(readBuf *buffer) (*FormArgDescri, error) {
 	//	FormArgDescri:   '$' Arg_Num { Arg_Name_Len Arg_Name Arg_No Arg_DType Arg_Preci_Scale }+
-	Arg_Num := binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+	Arg_Nums, err := readBuf.readNext(4, true)
+	if err != nil {
+		return nil, err
+	}
+	Arg_Num := binary.LittleEndian.Uint32(Arg_Nums)
 	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))
+		ArgNameLen, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		arg.ArgNameLen = binary.LittleEndian.Uint32(ArgNameLen)
 		//Arg_Name
-		arg.ArgName = readBuf.readNext(int(arg.ArgNameLen), false)
+		arg.ArgName, err = readBuf.readNext(int(arg.ArgNameLen), false)
+		if err != nil {
+			return nil, err
+		}
 		//Arg_No
-		arg.ArgNo = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+		ArgNo, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		arg.ArgNo = binary.LittleEndian.Uint32(ArgNo)
 		//Argg_DType
-		arg.ArgDType = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+		ArgDType, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		arg.ArgDType = binary.LittleEndian.Uint32(ArgDType)
 		//Arg_Preci_Scale
-		arg.ArgPreciScale = binary.LittleEndian.Uint32(readBuf.readNext(4, true))
+		ArgPreciScale, err := readBuf.readNext(4, true)
+		if err != nil {
+			return nil, err
+		}
+		arg.ArgPreciScale = binary.LittleEndian.Uint32(ArgPreciScale)
 		formArgDescri.Args = append(formArgDescri.Args, arg)
 	}
 	fmt.Printf("formArgDescri %#v \n", formArgDescri)

+ 156 - 0
xugu/xugu_parse_time.go

@@ -0,0 +1,156 @@
+package xugu
+
+type TIMESTAMP struct {
+	year     int
+	month    int
+	day      int
+	hour     int
+	minute   int
+	second   int
+	fraction int // 毫秒
+}
+
+// 是否是闰年
+func IsLeapYear(year int) bool {
+	return (year%4 == 0 && year%100 != 0) || (year%400 == 0)
+}
+
+// 月份到天数的映射
+var mtod = [2][13]int{
+	{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, // 非闰年
+	{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, // 闰年
+}
+
+func dt2dtm(t int64) TIMESTAMP {
+	var (
+		y, m, d, s int
+		mm, nn     int
+		wday       int
+		ms         int
+		rn_num     int
+	)
+
+	if t >= 0 { // 1970年以后
+		ms = int(t % 1000)
+		t /= 1000
+		s = int(t % 86400)
+		d = int(t / 86400)
+		wday = (d + 4) % 7
+		mm = d / 146097
+		nn = d % 146097
+		y = 1970 + 400*mm
+		mm = nn / 36524
+		nn = nn % 36524
+		y += 100 * mm
+		mm = nn / 1461
+		nn = nn % 1461
+		y += 4 * mm
+		if nn > 1096 {
+			y += 3
+		}
+		if nn > 730 && nn <= 1096 {
+			y += 2
+		}
+		if nn > 365 && nn <= 730 {
+			y++
+		}
+		if nn == 0 {
+			y--
+		}
+		rn_num = (y-1)/4 - (y-1)/100 + (y-1)/400
+		rn_num -= 477
+		d = d - 365*(y-1970) - rn_num
+	} else { // 1970年以前
+		ms = int(t % 1000)
+		t /= 1000
+		if ms != 0 {
+			ms += 1000
+			t--
+		}
+		s = int(t % 86400)
+		d = int(t / 86400)
+		if s != 0 {
+			s += 86400
+			d--
+		}
+		wday = (d + 4) % 7
+		if wday < 0 {
+			wday += 7
+		}
+		mm = d / 146097
+		nn = d % 146097
+		y = 1969 + 400*mm
+		mm = nn / 36524
+		nn = nn % 36524
+		y += 100 * mm
+		mm = nn / 1461
+		nn = nn % 1461
+		y += 4 * mm
+		if nn < -1096 {
+			y -= 3
+		}
+		if nn < -731 && nn >= -1096 {
+			y -= 2
+		}
+		if nn < -365 && nn >= -731 {
+			y--
+		}
+		if nn == 0 {
+			y++
+		}
+		rn_num = y/4 - y/100 + y/400
+		rn_num -= 477
+		d = d - 365*(y+1-1970) - rn_num
+		if IsLeapYear(y) {
+			d += 366
+		} else {
+			d += 365
+		}
+	}
+
+	if d < 0 {
+		y--
+		if IsLeapYear(y) {
+			d += 366
+		} else {
+			d += 365
+		}
+	}
+
+	d++
+	if IsLeapYear(y) {
+		if d > 366 {
+			d -= 366
+			y++
+		}
+	} else if d > 365 {
+		d -= 365
+		y++
+	}
+
+	if IsLeapYear(y) {
+		for m = 0; m <= 11; m++ {
+			if d > mtod[1][m] && d <= mtod[1][m+1] {
+				d -= mtod[1][m]
+				break
+			}
+		}
+	} else {
+		for m = 0; m <= 11; m++ {
+			if d > mtod[0][m] && d <= mtod[0][m+1] {
+				d -= mtod[0][m]
+				break
+			}
+		}
+	}
+
+	return TIMESTAMP{
+		year:     y,
+		month:    m + 1,
+		day:      d,
+		hour:     s / 3600,
+		minute:   (s % 3600) / 60,
+		second:   s % 60,
+		fraction: ms,
+	}
+}

+ 24 - 14
xugu/xugu_rows.go

@@ -3,8 +3,8 @@ package xugu
 import (
 	"database/sql/driver"
 	"encoding/binary"
-	"errors"
 	"fmt"
+	"io"
 	"reflect"
 	"time"
 )
@@ -21,12 +21,12 @@ func (row *xuguRows) Next(dest []driver.Value) error {
 	gt("Next()")
 	defer gt("Next() end")
 
-	fmt.Println("rowIdx", row.results.rowIdx, len(row.results.Values[0]))
 	if row.results.rowIdx >= len(row.results.Values[0]) {
-		return errors.New("The result set has been released")
+		//return errors.New("The result set has been released")
+		return io.EOF
 	}
 	//	fmt.Println(" -- int(row.results.Field_Num)", int(row.results.Field_Num))
-	fmt.Printf("这个 %#v", row.results.Values)
+
 	for j := 0; j < int(row.results.Field_Num); j++ {
 
 		coluType := row.results.Fields[j].FieldType
@@ -48,16 +48,28 @@ func (row *xuguRows) Next(dest []driver.Value) error {
 
 		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
+
+			if len(row.results.Values[j][row.results.rowIdx].Col_Data) == 0 {
+				dest[j] = nil
+			} else {
+				//timeTmp := binary.LittleEndian.Uint64(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)
+				timeTmp := binary.BigEndian.Uint64(row.results.Values[j][row.results.rowIdx].Col_Data)
+
+				//tv, _ := time.Parse("2006-01-02 15:04:05", string(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data)))
+				tv := time.Unix(0, int64(timeTmp)*1000000)
+				utcTime := tv.UTC()
+				dest[j] = utcTime
+			}
 
 		case fieldType_I1:
 			dest[j] = int8(row.results.Values[j][row.results.rowIdx].Col_Data[0])
 		case fieldType_I4:
-
-			dest[j] = binary.LittleEndian.Uint32(reverseBytes(row.results.Values[j][row.results.rowIdx].Col_Data))
-		case fieldType_CHAR:
-			dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
+			dest[j] = binary.BigEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data)
+		case fieldType_I8:
+			dest[j] = int64(binary.BigEndian.Uint64(row.results.Values[j][row.results.rowIdx].Col_Data))
+			//dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
+		case fieldType_CHAR, fieldType_NCHAR:
+			dest[j] = string(row.results.Values[j][row.results.rowIdx].Col_Data)
 		default:
 
 			//填入一行的数据
@@ -81,9 +93,8 @@ func (row *xuguRows) Columns() []string {
 
 	var columns []string
 
-	for i, v := range row.results.Fields {
+	for _, v := range row.results.Fields {
 		columns = append(columns, v.FieldName)
-		fmt.Printf("append(columns, v.FieldName) 个数%d ,v: %s\n", i+1, columns[i])
 	}
 
 	return columns
@@ -91,8 +102,7 @@ func (row *xuguRows) Columns() []string {
 
 func (row *xuguRows) ColumnTypeScanType(index int) reflect.Type {
 	fmt.Println(">>>>>ColumnTypeScanType ")
-	fmt.Printf("  -- row.results.Fields %#v \n", row.results.Fields[index].FieldType)
-	fmt.Printf("  -- row.results.Fields %#v \n", row.results.Fields[index].scanType())
+
 	return row.results.Fields[index].scanType()
 }
 

+ 10 - 24
xugu/xugu_sock.go

@@ -26,7 +26,6 @@ func xgSockOpenConn(ctx context.Context, pConn *xuguConn) error {
 		return errors.New("接收数据库连接失败:")
 	}
 
-	fmt.Println("读取数据库服务返回:", string(buffer[:n]))
 	if !bytes.Equal(buffer[:n], []byte("K")) {
 		return errors.New("数据库连接失败")
 	} else {
@@ -42,28 +41,23 @@ func sockSendPutStatement(pConn *xuguConn, sql []byte, values *[]xuguValue, para
 	}
 	// ?
 	pConn.sendBuff.Write([]byte("?"))
-	fmt.Println("?", pConn.sendBuff.Bytes())
 	// Comand_Len
 	sqlLength := uint32(len(sql))
 	var networkBytes [4]byte
 	binary.BigEndian.PutUint32(networkBytes[:], sqlLength)
 	pConn.sendBuff.Write(networkBytes[:])
-	fmt.Println("Comand_Len", pConn.sendBuff.Bytes())
 	//  Comand_str
 	pConn.sendBuff.Write(sql)
 	//'0' end
 	binary.BigEndian.PutUint32(networkBytes[:], 0)
 	pConn.sendBuff.Write([]byte{0})
 
-	fmt.Println("Comand_str + 0", pConn.sendBuff.Bytes())
 	// Param_num
 
 	var Param_num [4]byte
 	binary.BigEndian.PutUint32(Param_num[:], uint32(paramCount))
 	pConn.sendBuff.Write(Param_num[:])
 
-	fmt.Println("Param_num ", pConn.sendBuff.Bytes())
-
 	if values != nil {
 		//当缓冲区大于8190字节时,直接发送
 		if pConn.sendBuff.Len() > 8190 {
@@ -74,8 +68,6 @@ func sockSendPutStatement(pConn *xuguConn, sql []byte, values *[]xuguValue, para
 			}
 		}
 
-		fmt.Println(" sendBuff ", pConn.sendBuff.Bytes())
-
 		//发送后续参数
 		//	Param_num   { Param_name_len Param_name Param_INOUT Param_DType Param_Data_Len Param_Data }
 		for _, value := range *values {
@@ -83,55 +75,50 @@ func sockSendPutStatement(pConn *xuguConn, sql []byte, values *[]xuguValue, para
 			if value.paramName == nil {
 				var Param_name_len [2]byte
 				pConn.sendBuff.Write(Param_name_len[:])
-				fmt.Println("Param_name_len sendBuff ", pConn.sendBuff.Bytes())
+
 				//Param_name
 				// var Param_name []byte
 				// pConn.sendBuff.Write(Param_name)
-				fmt.Println("Param_name_data sendBuff ", pConn.sendBuff.Bytes())
+
 			} else {
 				var Param_name_len [2]byte
-				fmt.Println("paramName ", value.paramName)
+
 				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
 				pConn.sendBuff.Write(value.paramName[:])
-				fmt.Println("Param_name_data sendBuff ", pConn.sendBuff.Bytes())
+
 			}
 
 			//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 根据DType 修改长度
 			Param_Data_Len := make([]byte, 4)
 			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 根据DType 修改长度
 			//Param_Data := make([]byte, value.valueLength)
 			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())
+
 	return nil
 }
 
 func sockSendExecute(pConn *xuguConn) error {
 	fmt.Println("\n ---sockSendExecute")
-	fmt.Println("SockSendExecute msg: ", pConn.sendBuff.String())
+	//	fmt.Println("SockSendExecute msg: ", pConn.sendBuff.String())
 	_, err := pConn.conn.Write(pConn.sendBuff.Bytes())
 	if err != nil {
 		return err
@@ -141,9 +128,8 @@ func sockSendExecute(pConn *xuguConn) error {
 }
 
 func xuguSockRecvMsg(pConn *xuguConn) (*allResult, error) {
-	pConn.conn.Read(pConn.readBuff.buf)
-	fmt.Println("pConn.readBuff.buf ::", pConn.readBuff.buf, string(pConn.readBuff.buf))
-
+	n, _ := pConn.conn.Read(pConn.readBuff.buf)
+	pConn.readBuff.length += n
 	rs, err := parseMsg(&pConn.readBuff, pConn)
 	if err != nil {
 		fmt.Println("xuguPrepare parseMsg(&pConn.readBuff, pConn)")

+ 5 - 1
xugu/xugu_stmt.go

@@ -75,6 +75,10 @@ func (stmt *xuguStmt) Exec(args []driver.Value) (driver.Result, error) {
 	case selectResult:
 
 		return nil, errors.New("exec is Query error")
+	case updateResult:
+		return &xuguResult{affectedRows: int64(aR.u.UpdateNum), insertId: int64(0)}, nil
+	case insertResult:
+		return &xuguResult{affectedRows: int64(0), insertId: int64(aR.i.RowidLen)}, nil
 	case errInfo:
 
 		return nil, errors.New(string(aR.e.ErrStr))
@@ -122,7 +126,7 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 
 	switch aR.rt {
 	case selectResult:
-		fmt.Printf("selectResult %#v\n", aR.s)
+		
 		rows := &xuguRows{
 			rows_conn: stmt.stmt_conn,
 			results:   aR.s,