xugusql_stmt.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package xugu
  2. import (
  3. "database/sql/driver"
  4. "errors"
  5. "net"
  6. "unsafe"
  7. )
  8. type xugusqlStmt struct {
  9. // Context connection handle pointer
  10. stmt_conn net.Conn
  11. // Boolean value, used to identify whether
  12. // the executed SQL statement has been prepared
  13. // 布尔值,用于标识执行的 SQL 语句是否已准备好
  14. prepared bool
  15. // Accept the prepared code for
  16. // the prepared SQL statement
  17. // 接受已准备好 SQL 语句的准备代码
  18. prename string
  19. // Boolean value used to identify
  20. // whether the cursor is enabled
  21. // 布尔值,用于标识是否启用了游标
  22. curopend bool
  23. // Cursor name
  24. // 游标名称
  25. curname string
  26. // The number of parameters
  27. // in the executed SQL statement
  28. // 执行的 SQL 语句中的参数数量
  29. param_count int
  30. mysql string
  31. // Context result set handle pointer
  32. // 上下文结果集句柄指针
  33. result unsafe.Pointer
  34. }
  35. /* Collect error information from the database server */
  36. func (self *xugusqlStmt) get_error() error {
  37. // message := cgo_c_calloc(ERROR_BUFF_SIZE)
  38. // defer func() {
  39. // cgo_c_free(unsafe.Pointer(message))
  40. // }()
  41. // var length C.int
  42. // cgo_xgc_error(&self.stmt_conn, message, &length)
  43. // return errors.New(C.GoString(message))
  44. return errors.New("error")
  45. }
  46. /* {{ */
  47. func (self *xugusqlStmt) Close() error {
  48. if self.curopend {
  49. re := cgo_xgc_close_cursor(&self.stmt_conn, self.curname)
  50. if re < 0 {
  51. return self.get_error()
  52. }
  53. cgo_c_free(unsafe.Pointer(self.curname))
  54. self.curname = nil
  55. self.curopend = false
  56. }
  57. if self.prepared {
  58. re := cgo_xgc_unprepare(&self.stmt_conn, self.prename)
  59. if re < 0 {
  60. return self.get_error()
  61. }
  62. cgo_c_free(unsafe.Pointer(self.prename))
  63. self.prename = nil
  64. self.prepared = false
  65. }
  66. return nil
  67. }
  68. /* {{ */
  69. func (self *xugusqlStmt) NumInput() int {
  70. parser := &parse{
  71. bind_type: 0,
  72. param_count: 0,
  73. position: 0,
  74. }
  75. return parser.assertParamCount(self.mysql)
  76. }
  77. // Exec executes a prepared statement with the given arguments and
  78. // returns a Result summarizing the effect of the statement.
  79. func (self *xugusqlStmt) Exec(args []driver.Value) (driver.Result, error) {
  80. switch xgSqlType(self.mysql) {
  81. case SQL_SELECT:
  82. return nil, errors.New("Exec does not support queries")
  83. }
  84. if !self.prepared {
  85. return nil, errors.New("SQL statement is not Prepared")
  86. }
  87. parser := &parse{
  88. bind_type: 0,
  89. param_count: 0,
  90. position: 0,
  91. }
  92. if len(args) != 0 {
  93. for pos, param := range args {
  94. err := parser.assertParamType(param, pos)
  95. if err != nil {
  96. return nil, err
  97. }
  98. }
  99. if len(parser.Val) != parser.assertParamCount(self.mysql) {
  100. return nil, errors.New("The number of parameters does not match")
  101. }
  102. switch parser.assertBindType(self.mysql) {
  103. case BIND_PARAM_BY_POS:
  104. for pos, param := range parser.Val {
  105. if !param.islob {
  106. re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
  107. SQL_PARAM_INPUT, param.types,
  108. unsafe.Pointer(param.value), param.buff, &param.length)
  109. if re < 0 {
  110. return nil, self.get_error()
  111. }
  112. } else {
  113. re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
  114. SQL_PARAM_INPUT, param.types,
  115. unsafe.Pointer(&param.plob), param.buff, &param.length)
  116. if re < 0 {
  117. return nil, self.get_error()
  118. }
  119. }
  120. }
  121. case BIND_PARAM_BY_NAME:
  122. parser.assertParamName(self.mysql)
  123. for pos, param := range parser.Val {
  124. if !param.islob {
  125. re := cgo_xgc_bindparambyname(&self.stmt_conn, parser.param_names[pos],
  126. SQL_PARAM_INPUT, param.types, unsafe.Pointer(param.value),
  127. param.buff, &param.rcode, &param.length)
  128. if re < 0 {
  129. return nil, self.get_error()
  130. }
  131. } else {
  132. re := cgo_xgc_bindparambyname(&self.stmt_conn, parser.param_names[pos],
  133. SQL_PARAM_INPUT, param.types, unsafe.Pointer(&param.plob),
  134. param.buff, &param.rcode, &param.length)
  135. if re < 0 {
  136. return nil, self.get_error()
  137. }
  138. }
  139. }
  140. }
  141. }
  142. defer func() {
  143. cgo_c_free(unsafe.Pointer(sql))
  144. for pos, param := range parser.Val {
  145. if parser.bind_type == BIND_PARAM_BY_NAME {
  146. cgo_c_free(unsafe.Pointer(parser.param_names[pos]))
  147. }
  148. if !param.islob {
  149. cgo_c_free(unsafe.Pointer(param.value))
  150. } else {
  151. cgo_xgc_lob_distroy(&param.plob)
  152. }
  153. }
  154. }()
  155. result := &xugusqlResult{
  156. affectedRows: 0,
  157. insertId: 0,
  158. }
  159. re := cgo_xgc_execute(&self.stmt_conn, self.prename, self.curname, &self.result)
  160. if re < 0 {
  161. return nil, self.get_error()
  162. }
  163. var pCT, pCC, pRC, pEC C.int
  164. var pID = cgo_c_calloc(ROWID_BUFF_SIZE)
  165. re = cgo_xgc_get_result_set(&self.result, &pCT, &pCC, &pRC, &pEC, pID)
  166. if re < 0 {
  167. return nil, self.get_error()
  168. }
  169. cgo_c_free(unsafe.Pointer(pID))
  170. result.affectedRows = int64(pEC)
  171. return result, nil
  172. }
  173. // QueryContext executes a prepared query statement with the given arguments
  174. // and returns the query results as a *Rows.
  175. func (self *xugusqlStmt) Query(args []driver.Value) (driver.Rows, error) {
  176. sql := C.CString(self.mysql)
  177. if cgo_xgc_sql_type(sql) != SQL_SELECT {
  178. return nil, errors.New("The executed SQL statement is not a SELECT")
  179. }
  180. if !self.prepared {
  181. return nil, errors.New("SQL statement is not Prepared")
  182. }
  183. parser := &parse{
  184. bind_type: 0,
  185. param_count: 0,
  186. position: 0,
  187. }
  188. if len(args) != 0 {
  189. for pos, param := range args {
  190. err := parser.assertParamType(param, pos)
  191. if err != nil {
  192. return nil, err
  193. }
  194. }
  195. if len(parser.Val) != parser.assertParamCount(self.mysql) {
  196. return nil, errors.New("The number of parameters does not match")
  197. }
  198. switch parser.assertBindType(self.mysql) {
  199. case BIND_PARAM_BY_POS:
  200. for pos, param := range parser.Val {
  201. if !param.islob {
  202. re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
  203. SQL_PARAM_INPUT, param.types,
  204. unsafe.Pointer(param.value), param.buff, &param.length)
  205. if re < 0 {
  206. return nil, self.get_error()
  207. }
  208. } else {
  209. re := cgo_xgc_bindparambypos(&self.stmt_conn, pos+1,
  210. SQL_PARAM_INPUT, param.types,
  211. unsafe.Pointer(&param.plob), param.buff, &param.length)
  212. if re < 0 {
  213. return nil, self.get_error()
  214. }
  215. }
  216. }
  217. case BIND_PARAM_BY_NAME:
  218. parser.assertParamName(self.mysql)
  219. for pos, param := range parser.Val {
  220. if !param.islob {
  221. re := cgo_xgc_bindparambyname(&self.stmt_conn,
  222. parser.param_names[pos],
  223. SQL_PARAM_INPUT, param.types, unsafe.Pointer(param.value),
  224. param.buff, &param.rcode, &param.length)
  225. if re < 0 {
  226. return nil, self.get_error()
  227. }
  228. } else {
  229. re := cgo_xgc_bindparambyname(&self.stmt_conn,
  230. parser.param_names[pos],
  231. SQL_PARAM_INPUT, param.types, unsafe.Pointer(&param.plob),
  232. param.buff, &param.rcode, &param.length)
  233. if re < 0 {
  234. return nil, self.get_error()
  235. }
  236. }
  237. }
  238. }
  239. }
  240. defer func() {
  241. cgo_c_free(unsafe.Pointer(sql))
  242. for pos, param := range parser.Val {
  243. if parser.bind_type == BIND_PARAM_BY_NAME {
  244. cgo_c_free(unsafe.Pointer(parser.param_names[pos]))
  245. }
  246. if !param.islob {
  247. cgo_c_free(unsafe.Pointer(param.value))
  248. } else {
  249. cgo_xgc_lob_distroy(&param.plob)
  250. }
  251. }
  252. }()
  253. //if self.curname == nil {
  254. // self.curname = cgo_c_calloc(CURSOR_NAME_BUFF_SIZE)
  255. //}
  256. re := cgo_xgc_execute(&self.stmt_conn, self.prename, self.curname, &self.result)
  257. if re < 0 {
  258. return nil, self.get_error()
  259. }
  260. //re = cgo_xgc_fetch_with_cursor(&self.stmt_conn, self.curname, &self.result)
  261. //if re < 0 {
  262. // return nil, self.get_error()
  263. //}
  264. //self.curopend = true
  265. return &xugusqlRows{
  266. result: self.result,
  267. prepared: self.prepared,
  268. rows_conn: self.stmt_conn,
  269. }, nil
  270. }