Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle https://xorm.io
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

321 lines
8.2 KiB

  1. // Copyright 2016 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package xorm
  5. import (
  6. "database/sql"
  7. "fmt"
  8. "reflect"
  9. "strconv"
  10. "time"
  11. "github.com/go-xorm/core"
  12. )
  13. func (session *Session) query(sqlStr string, paramStr ...interface{}) ([]map[string][]byte, error) {
  14. session.queryPreprocess(&sqlStr, paramStr...)
  15. if session.isAutoCommit {
  16. return session.innerQuery2(sqlStr, paramStr...)
  17. }
  18. return session.txQuery(session.tx, sqlStr, paramStr...)
  19. }
  20. func (session *Session) txQuery(tx *core.Tx, sqlStr string, params ...interface{}) ([]map[string][]byte, error) {
  21. rows, err := tx.Query(sqlStr, params...)
  22. if err != nil {
  23. return nil, err
  24. }
  25. defer rows.Close()
  26. return rows2maps(rows)
  27. }
  28. func (session *Session) innerQuery(sqlStr string, params ...interface{}) (*core.Stmt, *core.Rows, error) {
  29. var callback func() (*core.Stmt, *core.Rows, error)
  30. if session.prepareStmt {
  31. callback = func() (*core.Stmt, *core.Rows, error) {
  32. stmt, err := session.doPrepare(sqlStr)
  33. if err != nil {
  34. return nil, nil, err
  35. }
  36. rows, err := stmt.Query(params...)
  37. if err != nil {
  38. return nil, nil, err
  39. }
  40. return stmt, rows, nil
  41. }
  42. } else {
  43. callback = func() (*core.Stmt, *core.Rows, error) {
  44. rows, err := session.DB().Query(sqlStr, params...)
  45. if err != nil {
  46. return nil, nil, err
  47. }
  48. return nil, rows, err
  49. }
  50. }
  51. stmt, rows, err := session.engine.logSQLQueryTime(sqlStr, params, callback)
  52. if err != nil {
  53. return nil, nil, err
  54. }
  55. return stmt, rows, nil
  56. }
  57. func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
  58. fields, err := rows.Columns()
  59. if err != nil {
  60. return nil, err
  61. }
  62. for rows.Next() {
  63. result, err := row2map(rows, fields)
  64. if err != nil {
  65. return nil, err
  66. }
  67. resultsSlice = append(resultsSlice, result)
  68. }
  69. return resultsSlice, nil
  70. }
  71. func value2Bytes(rawValue *reflect.Value) (data []byte, err error) {
  72. var str string
  73. str, err = reflect2value(rawValue)
  74. if err != nil {
  75. return
  76. }
  77. data = []byte(str)
  78. return
  79. }
  80. func row2map(rows *core.Rows, fields []string) (resultsMap map[string][]byte, err error) {
  81. result := make(map[string][]byte)
  82. scanResultContainers := make([]interface{}, len(fields))
  83. for i := 0; i < len(fields); i++ {
  84. var scanResultContainer interface{}
  85. scanResultContainers[i] = &scanResultContainer
  86. }
  87. if err := rows.Scan(scanResultContainers...); err != nil {
  88. return nil, err
  89. }
  90. for ii, key := range fields {
  91. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
  92. //if row is null then ignore
  93. if rawValue.Interface() == nil {
  94. //fmt.Println("ignore ...", key, rawValue)
  95. continue
  96. }
  97. if data, err := value2Bytes(&rawValue); err == nil {
  98. result[key] = data
  99. } else {
  100. return nil, err // !nashtsai! REVIEW, should return err or just error log?
  101. }
  102. }
  103. return result, nil
  104. }
  105. func (session *Session) innerQuery2(sqlStr string, params ...interface{}) ([]map[string][]byte, error) {
  106. _, rows, err := session.innerQuery(sqlStr, params...)
  107. if rows != nil {
  108. defer rows.Close()
  109. }
  110. if err != nil {
  111. return nil, err
  112. }
  113. return rows2maps(rows)
  114. }
  115. // Query runs a raw sql and return records as []map[string][]byte
  116. func (session *Session) Query(sqlStr string, paramStr ...interface{}) ([]map[string][]byte, error) {
  117. defer session.resetStatement()
  118. if session.isAutoClose {
  119. defer session.Close()
  120. }
  121. return session.query(sqlStr, paramStr...)
  122. }
  123. func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) {
  124. fields, err := rows.Columns()
  125. if err != nil {
  126. return nil, err
  127. }
  128. for rows.Next() {
  129. result, err := row2mapStr(rows, fields)
  130. if err != nil {
  131. return nil, err
  132. }
  133. resultsSlice = append(resultsSlice, result)
  134. }
  135. return resultsSlice, nil
  136. }
  137. func reflect2value(rawValue *reflect.Value) (str string, err error) {
  138. aa := reflect.TypeOf((*rawValue).Interface())
  139. vv := reflect.ValueOf((*rawValue).Interface())
  140. switch aa.Kind() {
  141. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  142. str = strconv.FormatInt(vv.Int(), 10)
  143. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  144. str = strconv.FormatUint(vv.Uint(), 10)
  145. case reflect.Float32, reflect.Float64:
  146. str = strconv.FormatFloat(vv.Float(), 'f', -1, 64)
  147. case reflect.String:
  148. str = vv.String()
  149. case reflect.Array, reflect.Slice:
  150. switch aa.Elem().Kind() {
  151. case reflect.Uint8:
  152. data := rawValue.Interface().([]byte)
  153. str = string(data)
  154. default:
  155. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  156. }
  157. // time type
  158. case reflect.Struct:
  159. if aa.ConvertibleTo(core.TimeType) {
  160. str = vv.Convert(core.TimeType).Interface().(time.Time).Format(time.RFC3339Nano)
  161. } else {
  162. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  163. }
  164. case reflect.Bool:
  165. str = strconv.FormatBool(vv.Bool())
  166. case reflect.Complex128, reflect.Complex64:
  167. str = fmt.Sprintf("%v", vv.Complex())
  168. /* TODO: unsupported types below
  169. case reflect.Map:
  170. case reflect.Ptr:
  171. case reflect.Uintptr:
  172. case reflect.UnsafePointer:
  173. case reflect.Chan, reflect.Func, reflect.Interface:
  174. */
  175. default:
  176. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  177. }
  178. return
  179. }
  180. func value2String(rawValue *reflect.Value) (data string, err error) {
  181. data, err = reflect2value(rawValue)
  182. if err != nil {
  183. return
  184. }
  185. return
  186. }
  187. func row2mapStr(rows *core.Rows, fields []string) (resultsMap map[string]string, err error) {
  188. result := make(map[string]string)
  189. scanResultContainers := make([]interface{}, len(fields))
  190. for i := 0; i < len(fields); i++ {
  191. var scanResultContainer interface{}
  192. scanResultContainers[i] = &scanResultContainer
  193. }
  194. if err := rows.Scan(scanResultContainers...); err != nil {
  195. return nil, err
  196. }
  197. for ii, key := range fields {
  198. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
  199. // if row is null then as empty string
  200. if rawValue.Interface() == nil {
  201. result[key] = ""
  202. continue
  203. }
  204. if data, err := value2String(&rawValue); err == nil {
  205. result[key] = data
  206. } else {
  207. return nil, err
  208. }
  209. }
  210. return result, nil
  211. }
  212. func txQuery2(tx *core.Tx, sqlStr string, params ...interface{}) ([]map[string]string, error) {
  213. rows, err := tx.Query(sqlStr, params...)
  214. if err != nil {
  215. return nil, err
  216. }
  217. defer rows.Close()
  218. return rows2Strings(rows)
  219. }
  220. func query2(db *core.DB, sqlStr string, params ...interface{}) ([]map[string]string, error) {
  221. rows, err := db.Query(sqlStr, params...)
  222. if err != nil {
  223. return nil, err
  224. }
  225. defer rows.Close()
  226. return rows2Strings(rows)
  227. }
  228. // QueryString runs a raw sql and return records as []map[string]string
  229. func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
  230. defer session.resetStatement()
  231. if session.isAutoClose {
  232. defer session.Close()
  233. }
  234. session.queryPreprocess(&sqlStr, args...)
  235. if session.isAutoCommit {
  236. return query2(session.DB(), sqlStr, args...)
  237. }
  238. return txQuery2(session.tx, sqlStr, args...)
  239. }
  240. // Execute sql
  241. func (session *Session) innerExec(sqlStr string, args ...interface{}) (sql.Result, error) {
  242. if session.prepareStmt {
  243. stmt, err := session.doPrepare(sqlStr)
  244. if err != nil {
  245. return nil, err
  246. }
  247. res, err := stmt.Exec(args...)
  248. if err != nil {
  249. return nil, err
  250. }
  251. return res, nil
  252. }
  253. return session.DB().Exec(sqlStr, args...)
  254. }
  255. func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) {
  256. for _, filter := range session.engine.dialect.Filters() {
  257. // TODO: for table name, it's no need to RefTable
  258. sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable)
  259. }
  260. session.saveLastSQL(sqlStr, args...)
  261. return session.engine.logSQLExecutionTime(sqlStr, args, func() (sql.Result, error) {
  262. if session.isAutoCommit {
  263. // FIXME: oci8 can not auto commit (github.com/mattn/go-oci8)
  264. if session.engine.dialect.DBType() == core.ORACLE {
  265. session.Begin()
  266. r, err := session.tx.Exec(sqlStr, args...)
  267. session.Commit()
  268. return r, err
  269. }
  270. return session.innerExec(sqlStr, args...)
  271. }
  272. return session.tx.Exec(sqlStr, args...)
  273. })
  274. }
  275. // Exec raw sql
  276. func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, error) {
  277. defer session.resetStatement()
  278. if session.isAutoClose {
  279. defer session.Close()
  280. }
  281. return session.exec(sqlStr, args...)
  282. }