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.
 
 
 
 
 

258 lines
6.5 KiB

  1. // Copyright 2017 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. "fmt"
  7. "reflect"
  8. "strconv"
  9. "time"
  10. "xorm.io/xorm/core"
  11. "xorm.io/xorm/schemas"
  12. )
  13. // Query runs a raw sql and return records as []map[string][]byte
  14. func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) {
  15. if session.isAutoClose {
  16. defer session.Close()
  17. }
  18. sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
  19. if err != nil {
  20. return nil, err
  21. }
  22. return session.queryBytes(sqlStr, args...)
  23. }
  24. func value2String(rawValue *reflect.Value) (str string, err error) {
  25. aa := reflect.TypeOf((*rawValue).Interface())
  26. vv := reflect.ValueOf((*rawValue).Interface())
  27. switch aa.Kind() {
  28. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  29. str = strconv.FormatInt(vv.Int(), 10)
  30. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  31. str = strconv.FormatUint(vv.Uint(), 10)
  32. case reflect.Float32, reflect.Float64:
  33. str = strconv.FormatFloat(vv.Float(), 'f', -1, 64)
  34. case reflect.String:
  35. str = vv.String()
  36. case reflect.Array, reflect.Slice:
  37. switch aa.Elem().Kind() {
  38. case reflect.Uint8:
  39. data := rawValue.Interface().([]byte)
  40. str = string(data)
  41. if str == "\x00" {
  42. str = "0"
  43. }
  44. default:
  45. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  46. }
  47. // time type
  48. case reflect.Struct:
  49. if aa.ConvertibleTo(schemas.TimeType) {
  50. str = vv.Convert(schemas.TimeType).Interface().(time.Time).Format(time.RFC3339Nano)
  51. } else {
  52. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  53. }
  54. case reflect.Bool:
  55. str = strconv.FormatBool(vv.Bool())
  56. case reflect.Complex128, reflect.Complex64:
  57. str = fmt.Sprintf("%v", vv.Complex())
  58. /* TODO: unsupported types below
  59. case reflect.Map:
  60. case reflect.Ptr:
  61. case reflect.Uintptr:
  62. case reflect.UnsafePointer:
  63. case reflect.Chan, reflect.Func, reflect.Interface:
  64. */
  65. default:
  66. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  67. }
  68. return
  69. }
  70. func row2mapStr(rows *core.Rows, fields []string) (resultsMap map[string]string, err error) {
  71. result := make(map[string]string)
  72. scanResultContainers := make([]interface{}, len(fields))
  73. for i := 0; i < len(fields); i++ {
  74. var scanResultContainer interface{}
  75. scanResultContainers[i] = &scanResultContainer
  76. }
  77. if err := rows.Scan(scanResultContainers...); err != nil {
  78. return nil, err
  79. }
  80. for ii, key := range fields {
  81. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
  82. // if row is null then as empty string
  83. if rawValue.Interface() == nil {
  84. result[key] = ""
  85. continue
  86. }
  87. if data, err := value2String(&rawValue); err == nil {
  88. result[key] = data
  89. } else {
  90. return nil, err
  91. }
  92. }
  93. return result, nil
  94. }
  95. func row2sliceStr(rows *core.Rows, fields []string) (results []string, err error) {
  96. result := make([]string, 0, len(fields))
  97. scanResultContainers := make([]interface{}, len(fields))
  98. for i := 0; i < len(fields); i++ {
  99. var scanResultContainer interface{}
  100. scanResultContainers[i] = &scanResultContainer
  101. }
  102. if err := rows.Scan(scanResultContainers...); err != nil {
  103. return nil, err
  104. }
  105. for i := 0; i < len(fields); i++ {
  106. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[i]))
  107. // if row is null then as empty string
  108. if rawValue.Interface() == nil {
  109. result = append(result, "")
  110. continue
  111. }
  112. if data, err := value2String(&rawValue); err == nil {
  113. result = append(result, data)
  114. } else {
  115. return nil, err
  116. }
  117. }
  118. return result, nil
  119. }
  120. func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) {
  121. fields, err := rows.Columns()
  122. if err != nil {
  123. return nil, err
  124. }
  125. for rows.Next() {
  126. result, err := row2mapStr(rows, fields)
  127. if err != nil {
  128. return nil, err
  129. }
  130. resultsSlice = append(resultsSlice, result)
  131. }
  132. return resultsSlice, nil
  133. }
  134. func rows2SliceString(rows *core.Rows) (resultsSlice [][]string, err error) {
  135. fields, err := rows.Columns()
  136. if err != nil {
  137. return nil, err
  138. }
  139. for rows.Next() {
  140. record, err := row2sliceStr(rows, fields)
  141. if err != nil {
  142. return nil, err
  143. }
  144. resultsSlice = append(resultsSlice, record)
  145. }
  146. return resultsSlice, nil
  147. }
  148. // QueryString runs a raw sql and return records as []map[string]string
  149. func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) {
  150. if session.isAutoClose {
  151. defer session.Close()
  152. }
  153. sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
  154. if err != nil {
  155. return nil, err
  156. }
  157. rows, err := session.queryRows(sqlStr, args...)
  158. if err != nil {
  159. return nil, err
  160. }
  161. defer rows.Close()
  162. return rows2Strings(rows)
  163. }
  164. // QuerySliceString runs a raw sql and return records as [][]string
  165. func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, error) {
  166. if session.isAutoClose {
  167. defer session.Close()
  168. }
  169. sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
  170. if err != nil {
  171. return nil, err
  172. }
  173. rows, err := session.queryRows(sqlStr, args...)
  174. if err != nil {
  175. return nil, err
  176. }
  177. defer rows.Close()
  178. return rows2SliceString(rows)
  179. }
  180. func row2mapInterface(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) {
  181. resultsMap = make(map[string]interface{}, len(fields))
  182. scanResultContainers := make([]interface{}, len(fields))
  183. for i := 0; i < len(fields); i++ {
  184. var scanResultContainer interface{}
  185. scanResultContainers[i] = &scanResultContainer
  186. }
  187. if err := rows.Scan(scanResultContainers...); err != nil {
  188. return nil, err
  189. }
  190. for ii, key := range fields {
  191. resultsMap[key] = reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])).Interface()
  192. }
  193. return
  194. }
  195. func rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
  196. fields, err := rows.Columns()
  197. if err != nil {
  198. return nil, err
  199. }
  200. for rows.Next() {
  201. result, err := row2mapInterface(rows, fields)
  202. if err != nil {
  203. return nil, err
  204. }
  205. resultsSlice = append(resultsSlice, result)
  206. }
  207. return resultsSlice, nil
  208. }
  209. // QueryInterface runs a raw sql and return records as []map[string]interface{}
  210. func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) {
  211. if session.isAutoClose {
  212. defer session.Close()
  213. }
  214. sqlStr, args, err := session.statement.GenQuerySQL(sqlOrArgs...)
  215. if err != nil {
  216. return nil, err
  217. }
  218. rows, err := session.queryRows(sqlStr, args...)
  219. if err != nil {
  220. return nil, err
  221. }
  222. defer rows.Close()
  223. return rows2Interfaces(rows)
  224. }