sql.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright 2018 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 builder
  5. import (
  6. sql2 "database/sql"
  7. "fmt"
  8. "reflect"
  9. "time"
  10. )
  11. func condToSQL(cond Cond) (string, []interface{}, error) {
  12. if cond == nil || !cond.IsValid() {
  13. return "", nil, nil
  14. }
  15. w := NewWriter()
  16. if err := cond.WriteTo(w); err != nil {
  17. return "", nil, err
  18. }
  19. return w.writer.String(), w.args, nil
  20. }
  21. func condToBoundSQL(cond Cond) (string, error) {
  22. if cond == nil || !cond.IsValid() {
  23. return "", nil
  24. }
  25. w := NewWriter()
  26. if err := cond.WriteTo(w); err != nil {
  27. return "", err
  28. }
  29. return ConvertToBoundSQL(w.writer.String(), w.args)
  30. }
  31. // ToSQL convert a builder or conditions to SQL and args
  32. func ToSQL(cond interface{}) (string, []interface{}, error) {
  33. switch cond.(type) {
  34. case Cond:
  35. return condToSQL(cond.(Cond))
  36. case *Builder:
  37. return cond.(*Builder).ToSQL()
  38. }
  39. return "", nil, ErrNotSupportType
  40. }
  41. // ToBoundSQL convert a builder or conditions to parameters bound SQL
  42. func ToBoundSQL(cond interface{}) (string, error) {
  43. switch cond.(type) {
  44. case Cond:
  45. return condToBoundSQL(cond.(Cond))
  46. case *Builder:
  47. return cond.(*Builder).ToBoundSQL()
  48. }
  49. return "", ErrNotSupportType
  50. }
  51. func noSQLQuoteNeeded(a interface{}) bool {
  52. switch a.(type) {
  53. case int, int8, int16, int32, int64:
  54. return true
  55. case uint, uint8, uint16, uint32, uint64:
  56. return true
  57. case float32, float64:
  58. return true
  59. case bool:
  60. return true
  61. case string:
  62. return false
  63. case time.Time, *time.Time:
  64. return false
  65. case expr, *expr:
  66. return true
  67. }
  68. t := reflect.TypeOf(a)
  69. switch t.Kind() {
  70. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  71. return true
  72. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  73. return true
  74. case reflect.Float32, reflect.Float64:
  75. return true
  76. case reflect.Bool:
  77. return true
  78. case reflect.String:
  79. return false
  80. }
  81. return false
  82. }
  83. // ConvertToBoundSQL will convert SQL and args to a bound SQL
  84. func ConvertToBoundSQL(sql string, args []interface{}) (string, error) {
  85. buf := StringBuilder{}
  86. var i, j, start int
  87. for ; i < len(sql); i++ {
  88. if sql[i] == '?' {
  89. _, err := buf.WriteString(sql[start:i])
  90. if err != nil {
  91. return "", err
  92. }
  93. start = i + 1
  94. if len(args) == j {
  95. return "", ErrNeedMoreArguments
  96. }
  97. arg := args[j]
  98. if namedArg, ok := arg.(sql2.NamedArg); ok {
  99. arg = namedArg.Value
  100. }
  101. if noSQLQuoteNeeded(arg) {
  102. _, err = fmt.Fprint(&buf, arg)
  103. } else {
  104. _, err = fmt.Fprintf(&buf, "'%v'", arg)
  105. }
  106. if err != nil {
  107. return "", err
  108. }
  109. j = j + 1
  110. }
  111. }
  112. _, err := buf.WriteString(sql[start:])
  113. if err != nil {
  114. return "", err
  115. }
  116. return buf.String(), nil
  117. }
  118. // ConvertToBoundSQL will convert SQL and args to a bound SQL
  119. func ConvertExprToBoundSQL(sql string, args []interface{}) (string,[]interface{}, error) {
  120. buf := StringBuilder{}
  121. var i, j, start int
  122. var sqlArgs []interface{}
  123. for ; i < len(sql); i++ {
  124. if sql[i] == '?' {
  125. _, err := buf.WriteString(sql[start:i])
  126. if err != nil {
  127. return "",sqlArgs, err
  128. }
  129. start = i + 1
  130. if len(args) == j {
  131. return "",sqlArgs, ErrNeedMoreArguments
  132. }
  133. arg := args[j]
  134. if exprArg, ok := arg.(expr);ok{
  135. arg = exprArg.sql
  136. _, err = fmt.Fprint(&buf, arg)
  137. if err != nil {
  138. return "",sqlArgs, err
  139. }
  140. for i,_:=range exprArg.args{
  141. sqlArgs = append(sqlArgs, exprArg.args[i])
  142. }
  143. }else{
  144. _, err = fmt.Fprint(&buf, "?")
  145. if err != nil {
  146. return "",sqlArgs, err
  147. }
  148. sqlArgs = append(sqlArgs, arg)
  149. }
  150. j = j + 1
  151. }
  152. }
  153. _, err := buf.WriteString(sql[start:])
  154. if err != nil {
  155. return "",sqlArgs, err
  156. }
  157. return buf.String(), sqlArgs,nil
  158. }
  159. // ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix
  160. func ConvertPlaceholder(sql, prefix string) (string, error) {
  161. buf := StringBuilder{}
  162. var i, j, start int
  163. for ; i < len(sql); i++ {
  164. if sql[i] == '?' {
  165. if _, err := buf.WriteString(sql[start:i]); err != nil {
  166. return "", err
  167. }
  168. start = i + 1
  169. j = j + 1
  170. if _, err := buf.WriteString(fmt.Sprintf("%v%d", prefix, j)); err != nil {
  171. return "", err
  172. }
  173. }
  174. }
  175. if _, err := buf.WriteString(sql[start:]); err != nil {
  176. return "", err
  177. }
  178. return buf.String(), nil
  179. }