package xugu import ( "database/sql/driver" "errors" "fmt" ) type xuguStmt struct { // 上下文连接句柄指针 stmt_conn *xuguConn // 布尔值,用于标识执行的 SQL 语句是否已准备好 prepared bool // 接受准备好的 SQL 语句的代码 prename []byte // 布尔值,用于标识游标是否启用 curopend bool // 游标名称 curname []byte // 执行的 SQL 语句中的参数数量 paramCount int mysql string //需替换的参数字段信息 parser *xuguParse } /* Collect error information from the database server */ func (self *xuguStmt) get_error() error { // message := cgo_c_calloc(ERROR_BUFF_SIZE) // defer func() { // cgo_c_free(unsafe.Pointer(message)) // }() // var length C.int // cgo_xgc_error(&self.stmt_conn, message, &length) // return errors.New(C.GoString(message)) return errors.New("xuguStmt error") } /* {{ */ func (stmt *xuguStmt) Close() error { fmt.Println("\n>>>>>> (stmt *xuguStmt) Close method called") return nil } func (stmt *xuguStmt) NumInput() int { fmt.Println("\n>>>>>(stmt *xuguStmt) NumInput()") parser := &xuguParse{ bind_type: 0, param_count: 0, position: 0, } fmt.Println("stmt.mysql: ", stmt.mysql) return parser.assertParamCount(stmt.mysql) //return 0 } func (stmt *xuguStmt) Exec(args []driver.Value) (driver.Result, error) { fmt.Println(">>>>>>>Exec method called") 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) } //处理服务器返回 stmt.stmt_conn.conn.Read(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)) //循环读,多条语句执行,会有多条语句返回 //读取一字节 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") // } } func (stmt *xuguStmt) Query(args []driver.Value) (driver.Rows, error) { 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") } if !stmt.prepared { return nil, errors.New("SQL statement is not Prepared") } 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 } } //fmt.Printf("len(parser.Val) = %d\n , parser.assertParamCount(stmt.mysql) = %d\n", 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.values { 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.values { 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") // } //最终发送消息给服务器 sockSendPutStatement(stmt.stmt_conn, []byte(stmt.mysql), nil, 0) XGC_Execute(stmt.stmt_conn) //----------------处理服务器查询返回 stmt.stmt_conn.conn.Read(stmt.stmt_conn.readBuff.buf) //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) if err != nil { fmt.Println("parseSelectResult parseSelectResult err", err.Error()) return nil, err } a := &xuguRows{ results: results, prepared: stmt.prepared, rows_conn: stmt.stmt_conn, } fmt.Println("\n>>>>>>stmt Query end==============================================================") return a, nil }