package xugu import ( "bytes" "encoding/binary" "errors" ) const RETURN_PREPARE_SELECT = 19665 func rhRecvStr(pConn *xugusqlConn, valp *[]byte) (int, error) { var len uint32 if err := rhRecvInt32(pConn, &len); err != nil { return -4, err } pBuff := make([]byte, len+1) if err := rhRecv(pConn, pBuff, len); err != nil { return -4, err } pBuff[len] = 0x0 *valp = pBuff return 0, nil } // 接收单个字符 func rhRecvChar(pConn *xugusqlConn, valp *byte) (bool, error) { var ch [1]byte err := rhRecv(pConn, ch[:], 1) if err != nil { return false, err } *valp = ch[0] return true, nil } // TODO : pConn.bkChar != 0x0 这一部分代码需要修改 func rhRecv(pConn *xugusqlConn, buff []byte, dLen uint32) error { //old_len := dLen if pConn.bkChar != 0x0 { buff[0] = pConn.bkChar pConn.bkChar = 0x0 buff = buff[1:] dLen-- } //接收加密登录信息 if dLen != 0 { for dLen != 0 { if pConn.useSSL { buffer := make([]byte, 1024) n, err := pConn.conn.Read(buffer) if err != nil { return err } else { xgCacheRecv(pConn, buffer, int32(n)) } if n <= 0 { return errors.New("read error") } } } // DECRYPT(p_conn, buff, old_len); //解密缓冲 } return nil } func rhRecvInt32(pconn *xugusqlConn, i *uint32) error { var buff [4]byte err := rhRecv(pconn, buff[:], 4) if err != nil { return err } // 将大端字节序转换为主机字节序 *i = binary.BigEndian.Uint32(buff[:]) return nil } func xgCacheRecv(pConn *xugusqlConn, buff []byte, dLen int32) (int, error) { return 0, nil } // 从连接中接收字段信息,并将其存储在 Result 结构体中。 func recvFiledsInfo(pConn *xugusqlConn, pRes *Result) (int, error) { var fieldNum uint32 //var pRet *FieldInfo if err := rhRecvInt32(pConn, &fieldNum); err != nil { return XG_NET_ERROR, err } if fieldNum > 4000 { return XG_NET_ERROR, errors.New("fieldNum >4000") } pRes.FieldNum = fieldNum pRet := make([]FieldInfo, fieldNum) //接收字段详细信息 for n := uint32(0); n < fieldNum; n++ { if ret, err := recvAttrDesItem(pConn, &pRet[n]); err != nil { return ret, err } } bytesN := (fieldNum*2 + 7) / 8 for n := uint32(0); n < fieldNum; n++ { pRet[n].Offset = bytesN bytesN += uint32(getSQLCType(pRet[n].TypeID)) } // TODO : 这里需要重新修改 // 在c代码中这里还加上了 ROW_HEAD_SIZE pRes.RowSize = bytesN + 24 pRes.ColInfos = pRet return 0, nil } // 接收字段属性描述 func recvAttrDesItem(pConn *xugusqlConn, pItem *FieldInfo) (int, error) { var nameLen uint32 var tabName []byte var alias []byte if err := rhRecvInt32(pConn, &nameLen); err != nil { return XG_NET_ERROR, err } if nameLen > 1024 { return XG_NET_ERROR, errors.New("nameLen >1024") } var name []byte if err := rhRecv(pConn, name, nameLen); err != nil { return XG_NET_ERROR, err } if ret := bytes.IndexByte(name, '%'); ret != -1 { alias = name[ret+1:] name = name[:ret-1] } if ret := bytes.IndexByte(name, '.'); ret != -1 { //如果 return_schema_on 为真,那么这里将得到 schema_name.tab_name。 tabName = name[:ret-1] name = name[ret+1:] } pItem.TabName = string(tabName) pItem.Name = string(name) pItem.Alias = string(alias) if err := rhRecvInt32(pConn, &pItem.TypeID); err != nil { return XG_NET_ERROR, err } if err := rhRecvInt32(pConn, &pItem.Modi); err != nil { return XG_NET_ERROR, err } if err := rhRecvInt32(pConn, &pItem.Flags); err != nil { return XG_NET_ERROR, err } pItem.CTypeID = uint32(getSQLCType(pItem.TypeID)) return 0, nil } func recvParamsInfo2(pConn *xugusqlConn, 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, ¶mNum) 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 }