GTong 10 months ago
parent
commit
6368c2ea96
15 changed files with 678 additions and 443 deletions
  1. 18 19
      main.go
  2. 26 0
      select A.ini
  3. 13 2
      xugu/buffer.go
  4. 1 0
      xugu/xugu_conn.go
  5. 5 3
      xugu/xugu_connector.go
  6. 2 2
      xugu/xugu_define.go
  7. 142 67
      xugu/xugu_fields.go
  8. 324 113
      xugu/xugu_parse.go
  9. 1 1
      xugu/xugu_prepare.go
  10. 35 22
      xugu/xugu_rows.go
  11. 6 5
      xugu/xugu_sock.go
  12. 0 174
      xugu/xugu_sock_recv2.go
  13. 72 35
      xugu/xugu_stmt.go
  14. 33 0
      xugu/xugu_utils.go
  15. 0 0
      参数映射失败.txt

+ 18 - 19
main.go

@@ -9,42 +9,41 @@ import (
 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")
 	//_, err = db.Exec("create table go_test(c1 int, c2 varchar);")
-	db.Ping()
+	//db.Ping()
 	if err != nil {
 		log.Fatal(err)
 	}
 
-	// row, err := db.Query("select * from gotest2;")
+	// stmt, err := db.Prepare("SELECT ? FROM gotest2;")
+	// stmt.Query("1")
+	//查询
+	// row, err := db.Query("select 1 from gotest2;")
 	// if err != nil {
 	// 	fmt.Println("查询错误", err)
 	// }
-	// fmt.Println("row", row)
-
 	// col, _ := row.Columns()
 	// fmt.Println("row.Columns(): ", col)
-
-	// type1, _ := row.ColumnTypes()
-
-	// fmt.Printf("type:%#v \n ", type1)
-
+	// fmt.Println("len(col)", len(col))
 	// pvals := make([]interface{}, len(col))
+	// for key, _ := range pvals {
+	// 	dest := make([]byte, 216)
+	// 	pvals[key] = &dest
+	// } /* end for */
 	// for row.Next() {
-	// 	fmt.Println("row.Next():main ")
-	// 	row.Scan(pvals)
+	// 	row.Scan(pvals...)
 	// 	for _, v := range pvals {
-	// 		fmt.Printf("pvals:%v\t \n", v)
-
-	// 		fmt.Printf("pvals:%v\t \n", (v.(*[]byte)))
+	// 		//fmt.Printf("pvals:%v\t \n", v) binary.LittleEndian.Uint32(col.Col_Data)
+	// 		//fmt.Printf("第%d次:  %s\t", k, string(*(v.(*[]byte))))
+	// 		//	fmt.Printf("pvals:%v\t \n", (v.(*[]byte)))
+	// 		fmt.Printf("结果 %s\t", string(*(v.(*[]byte))))
 	// 	}
-
 	// 	fmt.Printf("\n")
-	// 	break
 	// }
 
 	//消息类型为E
-	//db.Exec("drop table ta3;")
-
-	db.Exec("INSERT INTO  gotest VALUES('gc');")
+	r, err := db.Exec("drop table ta3;drop table ta33; ")
+	r.RowsAffected()
+	// db.Exec("INSERT INTO  gotest VALUES('gt3');")
 	db.Close()
 
 }

+ 26 - 0
select A.ini

@@ -80,3 +80,29 @@ gc
 
 K
 
+
+[]uint8 len: 2048, cap: 2048,
+[65,
+0,0,0,1,
+0,0,0,5,
+69,88,80,82,49,0,0,0,3,255,255,255,255,0,0,0,0,82,0,0,0,1,1,82,0,0,0,1,1,82,0,0,0,1,1,
+
+75
+
+
+"A
+\x00\x00\x00\x01
+\x00\x00\x00\x05
+EXPR1
+\x00\x00\x00\x03
+\xff\xff\xff\xff
+\x00\x00\x00\x00
+
+R\x00\x00\x00\x01
+\x01
+R\x00\x00\x00\x01
+\x01
+R\x00\x00\x00\x01
+\x01
+K
+

+ 13 - 2
xugu/buffer.go

@@ -44,7 +44,7 @@ func (b *buffer) peekChar() byte {
 }
 
 // 返回指定字节的切片
-func (b *buffer) readNext(need int) []byte {
+func (b *buffer) readNext(need int, reverse bool) []byte {
 	//长度不够返回
 	if len(b.buf[b.idx:]) < need {
 		//调用一次接收服务器消息
@@ -57,6 +57,17 @@ func (b *buffer) readNext(need int) []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])
-	return 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
+	} else {
+		return b.buf[offset:b.idx]
+	}
+
 }

+ 1 - 0
xugu/xugu_conn.go

@@ -61,6 +61,7 @@ func (xgConn *xuguConn) Begin() (driver.Tx, error) {
 }
 
 func (xgConn *xuguConn) Prepare(query string) (driver.Stmt, error) {
+	fmt.Println(">>>>>(xgConn *xuguConn) Prepare(query string)")
 	//判断sql类型
 	switch switchSQLType(query) {
 	case SQL_PROCEDURE:

+ 5 - 3
xugu/xugu_connector.go

@@ -15,6 +15,7 @@ type connector struct {
 // Driver implements driver.Connector interface.
 // Driver returns &XuguDriver{}
 func (conntor *connector) Driver() driver.Driver {
+	fmt.Println(">>>>>(conntor *connector) Driver()")
 	return &XuguDriver{}
 }
 
@@ -29,6 +30,7 @@ dsn解析
 接收来自服务端的握手请求
 */
 func (conntor *connector) Connect(ctx context.Context) (driver.Conn, error) {
+	fmt.Println(">>>>>(conntor *connector) Connect(ctx context.Context) ")
 	dsnConfig := parseDSN(conntor.dsn)
 
 	xgConn := &xuguConn{conn: nil}
@@ -53,9 +55,9 @@ func (conntor *connector) Connect(ctx context.Context) (driver.Conn, error) {
 	xgConn.Type = HT_CONN
 	xgConn.readBuff = newBuffer(xgConn.conn)
 	fmt.Println("连接串为: ", conntor.dsn)
-	re, _ := xgSockOpenConn(ctx, xgConn)
-	if re < 0 {
-		return nil, xgConn.get_error()
+	err = xgSockOpenConn(ctx, xgConn)
+	if err != nil {
+		return nil, err
 	}
 
 	return xgConn, nil

+ 2 - 2
xugu/xugu_define.go

@@ -50,8 +50,8 @@ const (
 	SQL_XG_C_BLOB int = 42
 	SQL_XG_C_NULL int = -11
 
-	BIND_PARAM_BY_NAME int = 62
-	BIND_PARAM_BY_POS  int = 63
+	BIND_PARAM_BY_NAME int = 2
+	BIND_PARAM_BY_POS  int = 1
 )
 
 // SQL类型常量

+ 142 - 67
xugu/xugu_fields.go

@@ -23,76 +23,150 @@ type xuguField struct {
 	fieldType fieldType
 }
 
-type fieldType byte
+type fieldType uint16
+
+// const (
+// 	fieldTypeBool fieldType = iota + 0x01
+// 	fieldTypeChar
+// 	fieldTypeTinyint
+// 	fieldTypeShort
+// 	fieldTypeInteger
+// 	fieldTypeBigint
+// 	fieldTypeFloat
+// 	fieldTypeDouble
+// 	fieldTypeNumeric
+// 	fieldTypeDate
+// 	fieldTypeTime
+// 	fieldTypeTimeTZ
+// 	fieldTypeDatetime   fieldType = 23
+// 	fieldTypeDatetimeTZ fieldType = 14
+// 	fieldTypeBinary     fieldType = 15
+// 	fieldTypeVarChar    fieldType = 30
+
+// 	fieldTypeInterval    fieldType = 21
+// 	fieldTypeIntervalY2M fieldType = 28
+// 	fieldTypeIntervalD2S fieldType = 31
+// 	fieldTypeLob         fieldType = 40
+// 	fieldTypeClob        fieldType = 41
+// 	fieldTypeBlob        fieldType = 42
+// )
 
 const (
-	fieldTypeBool fieldType = iota + 0x01
-	fieldTypeChar
-	fieldTypeTinyint
-	fieldTypeShort
-	fieldTypeInteger
-	fieldTypeBigint
-	fieldTypeFloat
-	fieldTypeDouble
-	fieldTypeNumeric
-	fieldTypeDate
-	fieldTypeTime
-	fieldTypeTimeTZ
-	fieldTypeDatetime   fieldType = 23
-	fieldTypeDatetimeTZ fieldType = 14
-	fieldTypeBinary     fieldType = 15
-	fieldTypeVarChar    fieldType = 30
-
-	fieldTypeInterval    fieldType = 21
-	fieldTypeIntervalY2M fieldType = 28
-	fieldTypeIntervalD2S fieldType = 31
-	fieldTypeLob         fieldType = 40
-	fieldTypeClob        fieldType = 41
-	fieldTypeBlob        fieldType = 42
+	fieldType_EMPTY fieldType = iota + 0x00
+	fieldType_NULL
+	fieldType_BOOL
+	fieldType_I1
+	fieldType_I2
+	fieldType_I4
+	fieldType_I8
+	fieldType_NUM
+	fieldType_R4
+	fieldType_R8
+
+	fieldType_DATE
+	fieldType_TIME
+	fieldType_TIME_TZ
+	fieldType_DATETIME
+	fieldType_DATETIME_TZ
+
+	fieldType_INTERVAL_Y
+	fieldType_INTERVAL_Y2M
+	fieldType_INTERVAL_M
+
+	fieldType_INTERVAL_D
+	fieldType_INTERVAL_D2H
+	fieldType_INTERVAL_H
+	fieldType_INTERVAL_D2M
+	fieldType_INTERVAL_H2M
+	fieldType_INTERVAL_MI
+	fieldType_INTERVAL_D2S
+	fieldType_INTERVAL_H2S
+	fieldType_INTERVAL_M2S
+	fieldType_INTERVAL_S
+
+	fieldType_ROWVER
+	fieldType_GUID
+	fieldType_CHAR
+	fieldType_NCHAR
+	fieldType_CLOB
+
+	fieldType_BINARY
+	fieldType_BLOB
+
+	fieldType_GEOM
+	fieldType_POINT
+	fieldType_BOX
+	fieldType_POLYLINE
+	fieldType_POLYGON
+
+	fieldType_BLOB_I
+	fieldType_BLOB_S
+	fieldType_BLOB_M
+	fieldType_BLOB_OM
+	fieldType_STREAM
+	fieldType_ROWID
+	fieldType_SIBLING
+	fieldType_MAX_SYS fieldType = 47
+
+	fieldType_BLADE_BEGIN fieldType = 101
+	fieldType_BLADE_END   fieldType = 1000
+
+	fieldType_OBJECT fieldType = 1001 // object type
+	fieldType_REFROW
+	fieldType_RECORD  // record type
+	fieldType_VARRAY  // array type
+	fieldType_TABLE   // table type
+	fieldType_ITABLE  // Idxby table
+	fieldType_CURSOR  // involved ref-record type (cannot change)
+	fieldType_REFCUR  // REF_CURSOR type
+	fieldType_ROWTYPE // ref row type
+	fieldType_COLTYPE // ref column type
+	fieldType_CUR_REC
+	fieldType_PARAM
 )
 
 /* {{ */
 func (self *FieldDescri) typeDatabaseName() string {
 	switch self.FieldType {
-	case fieldTypeBool:
+	case fieldType_BOOL:
 		return "BOOLEAN"
-	case fieldTypeChar, fieldTypeVarChar:
+	case fieldType_CHAR, fieldType_NCHAR:
 		return "CHAR"
-	case fieldTypeTinyint:
+	case fieldType_I1:
 		return "TINYINT"
-	case fieldTypeShort:
+	case fieldType_I2:
 		return "SHORT"
-	case fieldTypeInteger:
+	case fieldType_I4:
 		return "INTEGER"
-	case fieldTypeBigint:
+	case fieldType_I8:
 		return "BIGINT"
-	case fieldTypeFloat:
+	case fieldType_R4:
 		return "FLOAT"
-	case fieldTypeDouble:
+	case fieldType_R8:
 		return "DOUBLE"
-	case fieldTypeNumeric:
+	case fieldType_NUM:
 		return "NUMERIC"
-	case fieldTypeDate:
+	case fieldType_DATE:
 		return "DATE"
-	case fieldTypeTime:
+	case fieldType_TIME:
 		return "TIME"
-	case fieldTypeTimeTZ:
+	case fieldType_TIME_TZ:
 		return "TIMEZONE"
-	case fieldTypeDatetime:
+	case fieldType_DATETIME:
 		return "DATETIME"
-	case fieldTypeDatetimeTZ:
+	case fieldType_DATETIME_TZ:
 		return "DATETIME TIMEZONE"
-	case fieldTypeBinary:
+	case fieldType_BINARY:
 		return "BINARY"
-	case fieldTypeInterval:
-		return "INTERVAL"
-	case fieldTypeIntervalY2M:
+	case fieldType_INTERVAL_Y:
+		return "INTERVAL YEAR"
+	case fieldType_INTERVAL_Y2M:
 		return "INTERVAL YEAR TO MONTH"
-	case fieldTypeIntervalD2S:
+	case fieldType_INTERVAL_D2S:
 		return "INTERVAL DAY TO SECOND"
-	case fieldTypeClob:
+	case fieldType_CLOB:
 		return "CLOB"
-	case fieldTypeBlob:
+	case fieldType_BLOB:
 		return "BLOB"
 	default:
 		return ""
@@ -101,38 +175,39 @@ func (self *FieldDescri) typeDatabaseName() string {
 
 /* {{ */
 func (self *FieldDescri) scanType() reflect.Type {
+
 	switch self.FieldType {
 
-	case fieldTypeBool:
+	case fieldType_BOOL:
 		return scanTypeBool
-	case fieldTypeTinyint:
+	case fieldType_I1:
 		return scanTypeInt8
-	case fieldTypeShort:
+	case fieldType_I2:
 		return scanTypeInt16
-	case fieldTypeInteger:
+	case fieldType_I4:
 		return scanTypeInt32
-	case fieldTypeBigint:
+	case fieldType_I8:
 		return scanTypeInt64
-	case fieldTypeFloat:
+	case fieldType_R4:
 		return scanTypeFloat32
-	case fieldTypeDouble:
+	case fieldType_R8:
 		return scanTypeFloat64
-	case fieldTypeDate,
-		fieldTypeTime,
-		fieldTypeDatetime:
+	case fieldType_DATE,
+		fieldType_TIME,
+		fieldType_DATETIME:
 		return scanTypeNullTime
-	case fieldTypeTimeTZ,
-		fieldTypeDatetimeTZ,
-		fieldTypeChar,
-		fieldTypeVarChar,
-		fieldTypeBinary,
-		fieldTypeInterval,
-		fieldTypeNumeric,
-		fieldTypeIntervalY2M,
-		fieldTypeIntervalD2S,
-		fieldTypeLob,
-		fieldTypeClob,
-		fieldTypeBlob:
+	case fieldType_TIME_TZ,
+		fieldType_DATETIME_TZ,
+		fieldType_CHAR,
+		fieldType_NCHAR,
+		fieldType_BINARY,
+		//fieldTypeInterval,
+		fieldType_NUM,
+		fieldType_INTERVAL_Y2M,
+		fieldType_INTERVAL_D2S,
+		//fieldTypeLob,
+		fieldType_CLOB,
+		fieldType_BLOB:
 		return scanTypeRawBytes
 	default:
 		return scanTypeUnknown

+ 324 - 113
xugu/xugu_parse.go

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

+ 1 - 1
xugu/xugu_prepare.go

@@ -104,7 +104,7 @@ func xgCmdUnprepare(pConn *xuguConn, prepareName string) int {
 * p_res 结果集指针, 其中 servercursor_name 与 pres 不同时并存
  */
 func XGC_Execute(pConn *xuguConn, sql string) int {
-	fmt.Println("\n>>>>>XGC_Execute")
+	fmt.Println("\n ---XGC_Execute")
 	//发送没有参数的sql
 	SockSendCommand0(pConn, sql)
 	return 0

+ 35 - 22
xugu/xugu_rows.go

@@ -4,6 +4,8 @@ package xugu
 
 import (
 	"database/sql/driver"
+	"encoding/binary"
+	"errors"
 	"fmt"
 	"reflect"
 )
@@ -44,34 +46,45 @@ type xuguRows struct {
 // 关闭Rows时应特别注意,不要修改dest中缓冲区的值
 func (row *xuguRows) Next(dest []driver.Value) error {
 	fmt.Println(">>>>>(self *xuguRows) Next() ")
-	fmt.Println(" -- int(row.results.Field_Num)", int(row.results.Field_Num))
+	if row.results.rowIdx >= len(row.results.Values[0]) {
+		return errors.New("The result set has been released")
+	}
+	//	fmt.Println(" -- int(row.results.Field_Num)", int(row.results.Field_Num))
 	for j := 0; j < int(row.results.Field_Num); j++ {
 
 		coluType := row.results.Fields[j].FieldType
-		fmt.Println("  --coluType: ", coluType, row.results.Fields[j].typeDatabaseName())
+		//fmt.Println("  --coluType: ", coluType, row.results.Fields[j].typeDatabaseName())
 
 		switch coluType {
 
-		case fieldTypeDate:
+		case fieldType_DATE:
+
+		case fieldType_BINARY,
+			fieldType_CLOB, fieldType_BLOB:
 
-		case fieldTypeBinary, fieldTypeLob,
-			fieldTypeClob, fieldTypeBlob:
+		case fieldType_TIME,
+			fieldType_TIME_TZ:
 
-		case fieldTypeTime,
-			fieldTypeTimeTZ:
+		case fieldType_DATETIME,
+			fieldType_DATETIME_TZ:
+		case fieldType_I1:
+			dest[j] = int8(row.results.Values[j][row.results.rowIdx].Col_Data[0])
+		case fieldType_I4:
 
-		case fieldTypeDatetime,
-			fieldTypeDatetimeTZ:
+			dest[j] = binary.LittleEndian.Uint32(row.results.Values[j][row.results.rowIdx].Col_Data)
 
 		default:
-			fmt.Println("   ----(self *xuguRows) Next() default ")
+
+			//填入一行的数据
+			//TODO这里长度改为一行长度
 			dest[j] = make([]byte, len(row.results.Values))
-			dest[j] = row.results.Values[j][0].Col_Data
-			fmt.Println(" dest[j]:", dest[j])
-			fmt.Println(" row.results.Values[j][0].Col_Data:", string(row.results.Values[j][0].Col_Data))
+			// Values[字段][0]
+			dest[j] = row.results.Values[j][row.results.rowIdx].Col_Data
+
 		}
 	}
-	fmt.Println(" -dest: ", dest)
+	row.results.rowIdx++
+
 	return nil
 }
 
@@ -89,25 +102,25 @@ func (row *xuguRows) Columns() []string {
 
 	//columns := make([]string, int(row.results.Field_Num))
 	var columns []string
-	fmt.Println("字段总数row.results.Field_Num", int(row.results.Field_Num))
+
 	for i, v := range row.results.Fields {
 		columns = append(columns, v.FieldName)
-		fmt.Println("ppend(columns, v.FieldName)", i, columns[i])
+		fmt.Printf("append(columns, v.FieldName) 个数%d ,%s", i+1, columns[i])
 	}
 
-	fmt.Println(" -columns len  ", len(columns))
+	// fmt.Println(" -columns len  ", len(columns))
 
-	for i, v := range columns {
+	// for i, v := range columns {
 
-		fmt.Println("  -columns:  ", i, v)
-	}
+	// 	fmt.Println("  -columns:  ", i, v)
+	// }
 	return columns
 }
 
 func (row *xuguRows) ColumnTypeScanType(index int) reflect.Type {
 	fmt.Println(">>>>>ColumnTypeScanType ")
-	fmt.Printf("  -- row.results.Fields %#v \n", row.results.Fields)
-
+	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()
 }
 

+ 6 - 5
xugu/xugu_sock.go

@@ -6,26 +6,27 @@ import (
 	"fmt"
 )
 
-func xgSockOpenConn(ctx context.Context, pConn *xuguConn) (int, error) {
-	fmt.Println(">>>>>XGSOpenConn")
+func xgSockOpenConn(ctx context.Context, pConn *xuguConn) error {
+	fmt.Println(" ---xgSockOpenConn(ctx context.Context, pConn *xuguConn)")
 	//发送
 	//fmt.Printf("login   database = '%s' user = '%s'  password = '%s' version='201' ", pConn.Database, pConn.User, pConn.Password)
 	//	message := "login   database = 'SYSTEM' user = 'SYSDBA'  password = 'SYSDBA' version='201' "
 	dsnMessage := generateLoginString(pConn.dsnConfig)
 	_, err := pConn.conn.Write([]byte(dsnMessage))
 	if err != nil {
-		fmt.Println("conn 发送数据库连接失败:", err)
+		return errors.New("conn 发送数据库连接失败:")
 	}
 	fmt.Println("数据已发送:", dsnMessage)
 
 	buffer := make([]byte, 1024)
 	n, err := pConn.conn.Read(buffer)
 	if err != nil {
-		fmt.Println("Error reading from xuguserver:", err)
+
+		return errors.New("conn 接收数据库连接相应失败:")
 	}
 	fmt.Println("读取数据库服务返回:", string(buffer[:n]))
 	//SockSendCommand0(pConn, "set schema SYSTEM")
-	return 1, nil
+	return nil
 }
 
 func xgSockPrepare(pConn *xuguConn, sql string, prepareName *string) (int, error) {

+ 0 - 174
xugu/xugu_sock_recv2.go

@@ -2,7 +2,6 @@ package xugu
 
 import (
 	"bufio"
-	"io"
 )
 
 // ----------------------------------------------------------------------------------------------------
@@ -19,59 +18,7 @@ type SrvResponse struct {
 	Message       []*Message
 }
 
-type FormArgDescri struct {
-	ArgNum int
-	Args   []ArgDescri
-}
-
-type ArgDescri struct {
-	ArgNameLen    int
-	ArgName       string
-	ArgNo         int
-	ArgDType      int
-	ArgPreciScale int
-}
-
-type InsertResult struct {
-	RowidLen  int
-	RowidData []byte
-}
-
-type UpdateResult struct {
-	UpdateNum int
-}
-
-type DeleteResult struct {
-	DeleteNum int
-}
-
-type ProcRet struct {
-	RetDType   int
-	RetDataLen int
-	RetData    []byte
-}
-
-type OutParamRet struct {
-	OutParamNo    int
-	OutParamDType int
-	OutParamLen   int
-	OutParamData  []byte
-}
-
-type ErrInfo struct {
-	ErrStrLen int
-	ErrStr    string
-}
 
-type WarnInfo struct {
-	WarnStrLen int
-	WarnStr    string
-}
-
-type Message struct {
-	MsgStrLen int
-	MsgStr    string
-}
 
 // func parseResponse(conn net.Conn) (*SrvResponse, error) {
 // 	response := &SrvResponse{}
@@ -149,38 +96,6 @@ type Message struct {
 
 // 解析函数的实现,例如 parseFormArgDescri 等
 
-func parseFormArgDescri(reader *bufio.Reader) (*FormArgDescri, error) {
-	argNum, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	formArgDescri := &FormArgDescri{ArgNum: argNum}
-	for i := 0; i < argNum; i++ {
-		argDescri := ArgDescri{}
-		argDescri.ArgNameLen, err = readInt32(reader)
-		if err != nil {
-			return nil, err
-		}
-		argDescri.ArgName, err = readString(reader, argDescri.ArgNameLen)
-		if err != nil {
-			return nil, err
-		}
-		argDescri.ArgNo, err = readInt32(reader)
-		if err != nil {
-			return nil, err
-		}
-		argDescri.ArgDType, err = readInt32(reader)
-		if err != nil {
-			return nil, err
-		}
-		argDescri.ArgPreciScale, err = readInt32(reader)
-		if err != nil {
-			return nil, err
-		}
-		formArgDescri.Args = append(formArgDescri.Args, argDescri)
-	}
-	return formArgDescri, nil
-}
 
 func readString(reader *bufio.Reader, length int) (string, error) {
 	bytes := make([]byte, length)
@@ -215,92 +130,3 @@ func parseFieldDescri(reader *bufio.Reader) (FieldDescri, error) {
 
 	return fieldDescri, nil
 }
-
-func parseUpdateResult(reader *bufio.Reader) (*UpdateResult, error) {
-	updateNum, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	return &UpdateResult{UpdateNum: updateNum}, nil
-}
-func parseDeleteResult(reader *bufio.Reader) (*DeleteResult, error) {
-	deleteNum, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	return &DeleteResult{DeleteNum: deleteNum}, nil
-}
-func parseProcRet(reader *bufio.Reader) (*ProcRet, error) {
-	retDType, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	retDataLen, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	retData := make([]byte, retDataLen)
-	_, err = io.ReadFull(reader, retData)
-	if err != nil {
-		return nil, err
-	}
-	return &ProcRet{RetDType: retDType, RetDataLen: retDataLen, RetData: retData}, nil
-}
-func parseOutParamRet(reader *bufio.Reader) (*OutParamRet, error) {
-	outParamNo, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	outParamDType, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	outParamLen, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	outParamData := make([]byte, outParamLen)
-	_, err = io.ReadFull(reader, outParamData)
-	if err != nil {
-		return nil, err
-	}
-	return &OutParamRet{
-		OutParamNo:    outParamNo,
-		OutParamDType: outParamDType,
-		OutParamLen:   outParamLen,
-		OutParamData:  outParamData,
-	}, nil
-}
-func parseErrInfo(reader *bufio.Reader) (*ErrInfo, error) {
-	errStrLen, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	errStr, err := readString(reader, errStrLen)
-	if err != nil {
-		return nil, err
-	}
-	return &ErrInfo{ErrStrLen: errStrLen, ErrStr: errStr}, nil
-}
-func parseWarnInfo(reader *bufio.Reader) (*WarnInfo, error) {
-	warnStrLen, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	warnStr, err := readString(reader, warnStrLen)
-	if err != nil {
-		return nil, err
-	}
-	return &WarnInfo{WarnStrLen: warnStrLen, WarnStr: warnStr}, nil
-}
-func parseMessage(reader *bufio.Reader) (*Message, error) {
-	msgStrLen, err := readInt32(reader)
-	if err != nil {
-		return nil, err
-	}
-	msgStr, err := readString(reader, msgStrLen)
-	if err != nil {
-		return nil, err
-	}
-	return &Message{MsgStrLen: msgStrLen, MsgStr: msgStr}, nil
-}

+ 72 - 35
xugu/xugu_stmt.go

@@ -2,8 +2,6 @@ package xugu
 
 import (
 	"database/sql/driver"
-	"encoding/base64"
-	"encoding/binary"
 	"errors"
 	"fmt"
 	"unsafe"
@@ -54,7 +52,7 @@ func (stmt *xuguStmt) Close() error {
 }
 
 func (stmt *xuguStmt) NumInput() int {
-	fmt.Println("\n>>>>>NumInput method called")
+	fmt.Println("\n>>>>>(stmt *xuguStmt) NumInput()")
 
 	parser := &xuguParse{
 		bind_type:   0,
@@ -80,43 +78,57 @@ func (stmt *xuguStmt) Exec(args []driver.Value) (driver.Result, error) {
 	readBuf := stmt.stmt_conn.readBuff
 	//fmt.Println("Message from server:", (buffer[:n]))
 	fmt.Println("Message from server:", string(stmt.stmt_conn.readBuff.buf))
-	//读取一字节
-	char := readBuf.peekChar()
-	switch char {
-	case '$':
-		fmt.Println("消息类型为$")
-	case 'I':
-		readBuf.idx++
-		fmt.Println("消息类型为I")
-		//Rowid_Len
-		Rowid_Len := binary.BigEndian.Uint32(readBuf.readNext(4))
-		fmt.Println("Rowid_Len", Rowid_Len)
-		//Rowid_Data	// Base64 解码
-		Rowid_Data, err := base64.StdEncoding.DecodeString(string(readBuf.readNext(int(Rowid_Len))))
-		if err != nil {
-			fmt.Println("Error decoding:", err)
 
+	//循环读,多条语句执行,会有多条语句返回
+	//读取一字节
+	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)
 		}
-		fmt.Println("Rowid_Data: ", string(Rowid_Data))
-
-	case 'U':
-		fmt.Println("消息类型为U")
-	case 'D':
-		fmt.Println("消息类型为D")
-	case 'E':
-		fmt.Println("消息类型为E")
-	case 'W':
-		fmt.Println("消息类型为W")
-	case 'M':
-		fmt.Println("消息类型为M")
+
+		//return nil, errors.New("Exec not implemented")
+
 	}
 
-	//return nil, errors.New("Exec not implemented")
-	return result, nil
 }
 
 func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
-	fmt.Println("\n>>>>>>Query method called")
+	fmt.Println("\n>>>>>>(stmt *xuguStmt) Query(args []driver.Value) ")
 	fmt.Println("stmt.mysql: ", stmt.mysql)
 	if switchSQLType(stmt.mysql) != SQL_SELECT {
 		return nil, errors.New("The executed SQL statement is not a SELECT")
@@ -131,6 +143,7 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 		position:    0,
 	}
 
+	//参数绑定
 	if len(args) != 0 {
 		for pos, param := range args {
 			err := parser.assertParamType(param, pos)
@@ -139,6 +152,32 @@ 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) {
+			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 {
+				if !param.islob {
+					fmt.Printf("pos: %d, param %#v \n", pos, param)
+					stmt.mysql = parser.bindParamByPos(stmt.mysql)
+					fmt.Println("? 号替换参数后的 sql", stmt.mysql)
+				}
+			}
+		case BIND_PARAM_BY_NAME:
+			fmt.Println("--BIND_PARAM_BY_NAME")
+			parser.assertParamName(stmt.mysql)
+			for pos, param := range parser.Val {
+				if !param.islob {
+					fmt.Println("pos: ", pos, "param: ", param)
+				}
+			}
+		default:
+			fmt.Println("default")
+		}
 	}
 	// if len(parser.Val) != parser.assertParamCount(stmt.mysql) {
 	// 	return nil, errors.New("The number of parameters does not match")
@@ -160,8 +199,6 @@ func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) {
 		return nil, err
 	}
 
-	fmt.Println("results:", results)
-
 	a := &xuguRows{
 		results:   results,
 		prepared:  stmt.prepared,

+ 33 - 0
xugu/xugu_utils.go

@@ -1,6 +1,8 @@
 package xugu
 
 import (
+	"bytes"
+	"encoding/binary"
 	"fmt"
 	"strings"
 )
@@ -219,3 +221,34 @@ func needCopyV(xgtype int) bool {
 	}
 
 }
+
+// 整形转换成字节
+func IntToBytes(n uint32, b byte) ([]byte, error) {
+	switch b {
+	case 1:
+		tmp := int8(n)
+		bytesBuffer := bytes.NewBuffer([]byte{})
+		binary.Write(bytesBuffer, binary.BigEndian, &tmp)
+		return bytesBuffer.Bytes(), nil
+	case 2:
+		tmp := int16(n)
+		bytesBuffer := bytes.NewBuffer([]byte{})
+		binary.Write(bytesBuffer, binary.BigEndian, &tmp)
+		return bytesBuffer.Bytes(), nil
+	case 3, 4:
+		tmp := int32(n)
+		bytesBuffer := bytes.NewBuffer([]byte{})
+		binary.Write(bytesBuffer, binary.BigEndian, &tmp)
+		return bytesBuffer.Bytes(), nil
+	}
+	return nil, fmt.Errorf("IntToBytes b param is invaild")
+}
+
+// reverseBytes 反转 byte slice 的顺序
+func reverseBytes(b []byte) []byte {
+	reversed := make([]byte, len(b))
+	for i := range b {
+		reversed[i] = b[len(b)-1-i]
+	}
+	return reversed
+}

+ 0 - 0
参数映射失败.go → 参数映射失败.txt