session_query.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. "github.com/xormplus/core"
  11. )
  12. // Query runs a raw sql and return records as []map[string][]byte
  13. func (session *Session) QueryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) {
  14. if session.isAutoClose {
  15. defer session.Close()
  16. }
  17. return session.queryBytes(sqlStr, args...)
  18. }
  19. func value2String(rawValue *reflect.Value) (str string, err error) {
  20. aa := reflect.TypeOf((*rawValue).Interface())
  21. vv := reflect.ValueOf((*rawValue).Interface())
  22. switch aa.Kind() {
  23. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  24. str = strconv.FormatInt(vv.Int(), 10)
  25. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  26. str = strconv.FormatUint(vv.Uint(), 10)
  27. case reflect.Float32, reflect.Float64:
  28. str = strconv.FormatFloat(vv.Float(), 'f', -1, 64)
  29. case reflect.String:
  30. str = vv.String()
  31. case reflect.Array, reflect.Slice:
  32. switch aa.Elem().Kind() {
  33. case reflect.Uint8:
  34. data := rawValue.Interface().([]byte)
  35. str = string(data)
  36. if str == "\x00" {
  37. str = "0"
  38. }
  39. default:
  40. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  41. }
  42. // time type
  43. case reflect.Struct:
  44. if aa.ConvertibleTo(core.TimeType) {
  45. str = vv.Convert(core.TimeType).Interface().(time.Time).Format(time.RFC3339Nano)
  46. } else {
  47. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  48. }
  49. case reflect.Bool:
  50. str = strconv.FormatBool(vv.Bool())
  51. case reflect.Complex128, reflect.Complex64:
  52. str = fmt.Sprintf("%v", vv.Complex())
  53. /* TODO: unsupported types below
  54. case reflect.Map:
  55. case reflect.Ptr:
  56. case reflect.Uintptr:
  57. case reflect.UnsafePointer:
  58. case reflect.Chan, reflect.Func, reflect.Interface:
  59. */
  60. default:
  61. err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
  62. }
  63. return
  64. }
  65. func row2mapStr(rows *core.Rows, fields []string) (resultsMap map[string]string, err error) {
  66. result := make(map[string]string)
  67. scanResultContainers := make([]interface{}, len(fields))
  68. for i := 0; i < len(fields); i++ {
  69. var scanResultContainer interface{}
  70. scanResultContainers[i] = &scanResultContainer
  71. }
  72. if err := rows.Scan(scanResultContainers...); err != nil {
  73. return nil, err
  74. }
  75. for ii, key := range fields {
  76. rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
  77. // if row is null then as empty string
  78. if rawValue.Interface() == nil {
  79. result[key] = ""
  80. continue
  81. }
  82. if data, err := value2String(&rawValue); err == nil {
  83. result[key] = data
  84. } else {
  85. return nil, err
  86. }
  87. }
  88. return result, nil
  89. }
  90. func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) {
  91. fields, err := rows.Columns()
  92. if err != nil {
  93. return nil, err
  94. }
  95. for rows.Next() {
  96. result, err := row2mapStr(rows, fields)
  97. if err != nil {
  98. return nil, err
  99. }
  100. resultsSlice = append(resultsSlice, result)
  101. }
  102. return resultsSlice, nil
  103. }
  104. // QueryString runs a raw sql and return records as []map[string]string
  105. func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
  106. if session.isAutoClose {
  107. defer session.Close()
  108. }
  109. rows, err := session.queryRows(sqlStr, args...)
  110. if err != nil {
  111. return nil, err
  112. }
  113. defer rows.Close()
  114. return rows2Strings(rows)
  115. }
  116. func row2mapInterface(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) {
  117. resultsMap = make(map[string]interface{}, len(fields))
  118. scanResultContainers := make([]interface{}, len(fields))
  119. for i := 0; i < len(fields); i++ {
  120. var scanResultContainer interface{}
  121. scanResultContainers[i] = &scanResultContainer
  122. }
  123. if err := rows.Scan(scanResultContainers...); err != nil {
  124. return nil, err
  125. }
  126. for ii, key := range fields {
  127. resultsMap[key] = reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])).Interface()
  128. }
  129. return
  130. }
  131. func rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) {
  132. fields, err := rows.Columns()
  133. if err != nil {
  134. return nil, err
  135. }
  136. for rows.Next() {
  137. result, err := row2mapInterface(rows, fields)
  138. if err != nil {
  139. return nil, err
  140. }
  141. resultsSlice = append(resultsSlice, result)
  142. }
  143. return resultsSlice, nil
  144. }
  145. // QueryInterface runs a raw sql and return records as []map[string]interface{}
  146. func (session *Session) QueryInterface(sqlStr string, args ...interface{}) ([]map[string]interface{}, error) {
  147. if session.isAutoClose {
  148. defer session.Close()
  149. }
  150. rows, err := session.queryRows(sqlStr, args...)
  151. if err != nil {
  152. return nil, err
  153. }
  154. defer rows.Close()
  155. return rows2Interfaces(rows)
  156. }