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.

230 lines
5.4KB

  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. "reflect"
  8. "time"
  9. "xorm.io/builder"
  10. "xorm.io/core"
  11. )
  12. func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) {
  13. for _, filter := range session.engine.dialect.Filters() {
  14. *sqlStr = filter.Do(*sqlStr, session.engine.dialect, session.statement.RefTable)
  15. }
  16. session.lastSQL = *sqlStr
  17. session.lastSQLArgs = paramStr
  18. }
  19. func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Rows, error) {
  20. defer session.resetStatement()
  21. session.queryPreprocess(&sqlStr, args...)
  22. if session.showSQL {
  23. session.lastSQL = sqlStr
  24. session.lastSQLArgs = args
  25. if session.engine.showExecTime {
  26. b4ExecTime := time.Now()
  27. defer func() {
  28. execDuration := time.Since(b4ExecTime)
  29. if len(args) > 0 {
  30. session.engine.logger.Infof("[SQL] %s %#v - took: %v", sqlStr, args, execDuration)
  31. } else {
  32. session.engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration)
  33. }
  34. }()
  35. } else {
  36. if len(args) > 0 {
  37. session.engine.logger.Infof("[SQL] %v %#v", sqlStr, args)
  38. } else {
  39. session.engine.logger.Infof("[SQL] %v", sqlStr)
  40. }
  41. }
  42. }
  43. if session.isAutoCommit {
  44. var db *core.DB
  45. if session.sessionType == groupSession {
  46. db = session.engine.engineGroup.Slave().DB()
  47. } else {
  48. db = session.DB()
  49. }
  50. if session.prepareStmt {
  51. // don't clear stmt since session will cache them
  52. stmt, err := session.doPrepare(db, sqlStr)
  53. if err != nil {
  54. return nil, err
  55. }
  56. rows, err := stmt.QueryContext(session.ctx, args...)
  57. if err != nil {
  58. return nil, err
  59. }
  60. return rows, nil
  61. }
  62. rows, err := db.QueryContext(session.ctx, sqlStr, args...)
  63. if err != nil {
  64. return nil, err
  65. }
  66. return rows, nil
  67. }
  68. rows, err := session.tx.QueryContext(session.ctx, sqlStr, args...)
  69. if err != nil {
  70. return nil, err
  71. }
  72. return rows, nil
  73. }
  74. func (session *Session) queryRow(sqlStr string, args ...interface{}) *core.Row {
  75. return core.NewRow(session.queryRows(sqlStr, args...))
  76. }
  77. func value2Bytes(rawValue *reflect.Value) ([]byte, error) {
  78. str, err := value2String(rawValue)
  79. if err != nil {
  80. return nil, err
  81. }
  82. return []byte(str), nil
  83. }
  84. func row2map(rows *core.Rows, fields []string) (resultsMap map[string][]byte, err error) {
  85. result := make(map[string][]byte)
  86. scanResultContainers := make([]interface{}, len(fields))
  87. for i := 0; i < len(fields); i++ {
  88. var scanResultContainer interface{}
  89. scanResultContainers[i] = &scanResultContainer
  90. }
  91. if err := rows.Scan(scanResultContainers...); err != nil {
  92. return nil, err
  93. }
  94. for ii, key := range fields {
  95. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
  96. //if row is null then ignore
  97. if rawValue.Interface() == nil {
  98. result[key] = []byte{}
  99. continue
  100. }
  101. if data, err := value2Bytes(&rawValue); err == nil {
  102. result[key] = data
  103. } else {
  104. return nil, err // !nashtsai! REVIEW, should return err or just error log?
  105. }
  106. }
  107. return result, nil
  108. }
  109. func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
  110. fields, err := rows.Columns()
  111. if err != nil {
  112. return nil, err
  113. }
  114. for rows.Next() {
  115. result, err := row2map(rows, fields)
  116. if err != nil {
  117. return nil, err
  118. }
  119. resultsSlice = append(resultsSlice, result)
  120. }
  121. return resultsSlice, nil
  122. }
  123. func (session *Session) queryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) {
  124. rows, err := session.queryRows(sqlStr, args...)
  125. if err != nil {
  126. return nil, err
  127. }
  128. defer rows.Close()
  129. return rows2maps(rows)
  130. }
  131. func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) {
  132. defer session.resetStatement()
  133. session.queryPreprocess(&sqlStr, args...)
  134. if session.engine.showSQL {
  135. if session.engine.showExecTime {
  136. b4ExecTime := time.Now()
  137. defer func() {
  138. execDuration := time.Since(b4ExecTime)
  139. if len(args) > 0 {
  140. session.engine.logger.Infof("[SQL] %s %#v - took: %v", sqlStr, args, execDuration)
  141. } else {
  142. session.engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration)
  143. }
  144. }()
  145. } else {
  146. if len(args) > 0 {
  147. session.engine.logger.Infof("[SQL] %v %#v", sqlStr, args)
  148. } else {
  149. session.engine.logger.Infof("[SQL] %v", sqlStr)
  150. }
  151. }
  152. }
  153. if !session.isAutoCommit {
  154. return session.tx.ExecContext(session.ctx, sqlStr, args...)
  155. }
  156. if session.prepareStmt {
  157. stmt, err := session.doPrepare(session.DB(), sqlStr)
  158. if err != nil {
  159. return nil, err
  160. }
  161. res, err := stmt.ExecContext(session.ctx, args...)
  162. if err != nil {
  163. return nil, err
  164. }
  165. return res, nil
  166. }
  167. return session.DB().ExecContext(session.ctx, sqlStr, args...)
  168. }
  169. func convertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) {
  170. switch sqlOrArgs[0].(type) {
  171. case string:
  172. return sqlOrArgs[0].(string), sqlOrArgs[1:], nil
  173. case *builder.Builder:
  174. return sqlOrArgs[0].(*builder.Builder).ToSQL()
  175. case builder.Builder:
  176. bd := sqlOrArgs[0].(builder.Builder)
  177. return bd.ToSQL()
  178. }
  179. return "", nil, ErrUnSupportedType
  180. }
  181. // Exec raw sql
  182. func (session *Session) Exec(sqlOrArgs ...interface{}) (sql.Result, error) {
  183. if session.isAutoClose {
  184. defer session.Close()
  185. }
  186. if len(sqlOrArgs) == 0 {
  187. return nil, ErrUnSupportedType
  188. }
  189. sqlStr, args, err := convertSQLOrArgs(sqlOrArgs...)
  190. if err != nil {
  191. return nil, err
  192. }
  193. return session.exec(sqlStr, args...)
  194. }