123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- package xugusql
- import (
- "C"
- "database/sql/driver"
- "errors"
- "unsafe"
- )
- type xugusqlStmt struct {
- // Context connection handle pointer
- stmt_conn unsafe.Pointer
- // Boolean value, used to identify whether
- // the executed SQL statement has been prepared
- prepared bool
- // Accept the prepared code for
- // the prepared SQL statement
- prename *C.char
- // Boolean value used to identify
- // whether the cursor is enabled
- curopend bool
- // Cursor name
- curname *C.char
- // The number of parameters
- // in the executed SQL statement
- param_count int
- mysql string
- // Context result set handle pointer
- result unsafe.Pointer
- }
- /* Collect error information from the database server */
- func (self *xugusqlStmt) 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))
- }
- /* {{ */
- func (self *xugusqlStmt) Close() error {
- if self.curopend {
- re := cgo_xgc_close_cursor(&self.stmt_conn, self.curname)
- if re < 0 {
- return self.get_error()
- }
- cgo_c_free(unsafe.Pointer(self.curname))
- self.curname = nil
- self.curopend = false
- }
- if self.prepared {
- re := cgo_xgc_unprepare(&self.stmt_conn, self.prename)
- if re < 0 {
- return self.get_error()
- }
- cgo_c_free(unsafe.Pointer(self.prename))
- self.prename = nil
- self.prepared = false
- }
- return nil
- }
- /* {{ */
- func (self *xugusqlStmt) NumInput() int {
- parser := &parse{
- bind_type: 0,
- param_count: 0,
- position: 0,
- }
- return parser.assertParamCount(self.mysql)
- }
- // Exec executes a prepared statement with the given arguments and
- // returns a Result summarizing the effect of the statement.
- func (self *xugusqlStmt) Exec(args []driver.Value) (driver.Result, error) {
- sql := C.CString(self.mysql)
- switch cgo_xgc_sql_type(sql) {
- case SQL_SELECT:
- return nil, errors.New("Exec does not support queries")
- }
- if !self.prepared {
- return nil, errors.New("SQL statement is not Prepared")
- }
- parser := &parse{
- 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.Val) != parser.assertParamCount(self.mysql) {
- return nil, errors.New("The number of parameters does not match")
- }
- switch parser.assertBindType(self.mysql) {
- case BIND_PARAM_BY_POS:
- for pos, param := range parser.Val {
- if !param.islob {
- re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
- SQL_PARAM_INPUT, param.types,
- unsafe.Pointer(param.value), param.buff, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- } else {
- re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
- SQL_PARAM_INPUT, param.types,
- unsafe.Pointer(¶m.plob), param.buff, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- }
- }
- case BIND_PARAM_BY_NAME:
- parser.assertParamName(self.mysql)
- for pos, param := range parser.Val {
- if !param.islob {
- re := cgo_xgc_bindparambyname(&self.stmt_conn, parser.param_names[pos],
- SQL_PARAM_INPUT, param.types, unsafe.Pointer(param.value),
- param.buff, ¶m.rcode, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- } else {
- re := cgo_xgc_bindparambyname(&self.stmt_conn, parser.param_names[pos],
- SQL_PARAM_INPUT, param.types, unsafe.Pointer(¶m.plob),
- param.buff, ¶m.rcode, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- }
- }
- }
- }
- defer func() {
- cgo_c_free(unsafe.Pointer(sql))
- for pos, param := range parser.Val {
- if parser.bind_type == BIND_PARAM_BY_NAME {
- cgo_c_free(unsafe.Pointer(parser.param_names[pos]))
- }
- if !param.islob {
- cgo_c_free(unsafe.Pointer(param.value))
- } else {
- cgo_xgc_lob_distroy(¶m.plob)
- }
- }
- }()
- result := &xugusqlResult{
- affectedRows: 0,
- insertId: 0,
- }
- re := cgo_xgc_execute(&self.stmt_conn, self.prename, self.curname, &self.result)
- if re < 0 {
- return nil, self.get_error()
- }
- var pCT, pCC, pRC, pEC C.int
- var pID = cgo_c_calloc(ROWID_BUFF_SIZE)
- re = cgo_xgc_get_result_set(&self.result, &pCT, &pCC, &pRC, &pEC, pID)
- if re < 0 {
- return nil, self.get_error()
- }
- cgo_c_free(unsafe.Pointer(pID))
- result.affectedRows = int64(pEC)
- return result, nil
- }
- // QueryContext executes a prepared query statement with the given arguments
- // and returns the query results as a *Rows.
- func (self *xugusqlStmt) Query(args []driver.Value) (driver.Rows, error) {
- sql := C.CString(self.mysql)
- if cgo_xgc_sql_type(sql) != SQL_SELECT {
- return nil, errors.New("The executed SQL statement is not a SELECT")
- }
- if !self.prepared {
- return nil, errors.New("SQL statement is not Prepared")
- }
- parser := &parse{
- 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.Val) != parser.assertParamCount(self.mysql) {
- return nil, errors.New("The number of parameters does not match")
- }
- switch parser.assertBindType(self.mysql) {
- case BIND_PARAM_BY_POS:
- for pos, param := range parser.Val {
- if !param.islob {
- re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
- SQL_PARAM_INPUT, param.types,
- unsafe.Pointer(param.value), param.buff, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- } else {
- re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
- SQL_PARAM_INPUT, param.types,
- unsafe.Pointer(¶m.plob), param.buff, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- }
- }
- case BIND_PARAM_BY_NAME:
- parser.assertParamName(self.mysql)
- for pos, param := range parser.Val {
- if !param.islob {
- re := cgo_xgc_bindparambyname(&self.stmt_conn,
- parser.param_names[pos],
- SQL_PARAM_INPUT, param.types, unsafe.Pointer(param.value),
- param.buff, ¶m.rcode, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- } else {
- re := cgo_xgc_bindparambyname(&self.stmt_conn,
- parser.param_names[pos],
- SQL_PARAM_INPUT, param.types, unsafe.Pointer(¶m.plob),
- param.buff, ¶m.rcode, ¶m.length)
- if re < 0 {
- return nil, self.get_error()
- }
- }
- }
- }
- }
- defer func() {
- cgo_c_free(unsafe.Pointer(sql))
- for pos, param := range parser.Val {
- if parser.bind_type == BIND_PARAM_BY_NAME {
- cgo_c_free(unsafe.Pointer(parser.param_names[pos]))
- }
- if !param.islob {
- cgo_c_free(unsafe.Pointer(param.value))
- } else {
- cgo_xgc_lob_distroy(¶m.plob)
- }
- }
- }()
- //if self.curname == nil {
- // self.curname = cgo_c_calloc(CURSOR_NAME_BUFF_SIZE)
- //}
- re := cgo_xgc_execute(&self.stmt_conn, self.prename, self.curname, &self.result)
- if re < 0 {
- return nil, self.get_error()
- }
- //re = cgo_xgc_fetch_with_cursor(&self.stmt_conn, self.curname, &self.result)
- //if re < 0 {
- // return nil, self.get_error()
- //}
- //self.curopend = true
- return &xugusqlRows{
- result: self.result,
- prepared: self.prepared,
- rows_conn: self.stmt_conn,
- }, nil
- }
|