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.
 
 
 
 
 

235 line
6.0 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. "database/sql/driver"
  7. "fmt"
  8. "reflect"
  9. "strings"
  10. "time"
  11. "xorm.io/builder"
  12. "xorm.io/xorm/convert"
  13. "xorm.io/xorm/internal/utils"
  14. "xorm.io/xorm/schemas"
  15. )
  16. func (engine *Engine) buildConds(table *schemas.Table, bean interface{},
  17. includeVersion bool, includeUpdated bool, includeNil bool,
  18. includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
  19. mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool) (builder.Cond, error) {
  20. var conds []builder.Cond
  21. for _, col := range table.Columns() {
  22. if !includeVersion && col.IsVersion {
  23. continue
  24. }
  25. if !includeUpdated && col.IsUpdated {
  26. continue
  27. }
  28. if !includeAutoIncr && col.IsAutoIncrement {
  29. continue
  30. }
  31. if engine.dialect.DBType() == schemas.MSSQL && (col.SQLType.Name == schemas.Text || col.SQLType.IsBlob() || col.SQLType.Name == schemas.TimeStampz) {
  32. continue
  33. }
  34. if col.SQLType.IsJson() {
  35. continue
  36. }
  37. var colName string
  38. if addedTableName {
  39. var nm = tableName
  40. if len(aliasName) > 0 {
  41. nm = aliasName
  42. }
  43. colName = engine.Quote(nm) + "." + engine.Quote(col.Name)
  44. } else {
  45. colName = engine.Quote(col.Name)
  46. }
  47. fieldValuePtr, err := col.ValueOf(bean)
  48. if err != nil {
  49. if !strings.Contains(err.Error(), "is not valid") {
  50. engine.logger.Warn(err)
  51. }
  52. continue
  53. }
  54. if col.IsDeleted && !unscoped { // tag "deleted" is enabled
  55. conds = append(conds, engine.CondDeleted(col))
  56. }
  57. fieldValue := *fieldValuePtr
  58. if fieldValue.Interface() == nil {
  59. continue
  60. }
  61. fieldType := reflect.TypeOf(fieldValue.Interface())
  62. requiredField := useAllCols
  63. if b, ok := getFlagForColumn(mustColumnMap, col); ok {
  64. if b {
  65. requiredField = true
  66. } else {
  67. continue
  68. }
  69. }
  70. if fieldType.Kind() == reflect.Ptr {
  71. if fieldValue.IsNil() {
  72. if includeNil {
  73. conds = append(conds, builder.Eq{colName: nil})
  74. }
  75. continue
  76. } else if !fieldValue.IsValid() {
  77. continue
  78. } else {
  79. // dereference ptr type to instance type
  80. fieldValue = fieldValue.Elem()
  81. fieldType = reflect.TypeOf(fieldValue.Interface())
  82. requiredField = true
  83. }
  84. }
  85. var val interface{}
  86. switch fieldType.Kind() {
  87. case reflect.Bool:
  88. if allUseBool || requiredField {
  89. val = fieldValue.Interface()
  90. } else {
  91. // if a bool in a struct, it will not be as a condition because it default is false,
  92. // please use Where() instead
  93. continue
  94. }
  95. case reflect.String:
  96. if !requiredField && fieldValue.String() == "" {
  97. continue
  98. }
  99. // for MyString, should convert to string or panic
  100. if fieldType.String() != reflect.String.String() {
  101. val = fieldValue.String()
  102. } else {
  103. val = fieldValue.Interface()
  104. }
  105. case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
  106. if !requiredField && fieldValue.Int() == 0 {
  107. continue
  108. }
  109. val = fieldValue.Interface()
  110. case reflect.Float32, reflect.Float64:
  111. if !requiredField && fieldValue.Float() == 0.0 {
  112. continue
  113. }
  114. val = fieldValue.Interface()
  115. case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
  116. if !requiredField && fieldValue.Uint() == 0 {
  117. continue
  118. }
  119. t := int64(fieldValue.Uint())
  120. val = reflect.ValueOf(&t).Interface()
  121. case reflect.Struct:
  122. if fieldType.ConvertibleTo(schemas.TimeType) {
  123. t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
  124. if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
  125. continue
  126. }
  127. val = engine.formatColTime(col, t)
  128. } else if _, ok := reflect.New(fieldType).Interface().(convert.Conversion); ok {
  129. continue
  130. } else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
  131. val, _ = valNul.Value()
  132. if val == nil {
  133. continue
  134. }
  135. } else {
  136. if col.SQLType.IsJson() {
  137. if col.SQLType.IsText() {
  138. bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface())
  139. if err != nil {
  140. engine.logger.Error(err)
  141. continue
  142. }
  143. val = string(bytes)
  144. } else if col.SQLType.IsBlob() {
  145. var bytes []byte
  146. var err error
  147. bytes, err = DefaultJSONHandler.Marshal(fieldValue.Interface())
  148. if err != nil {
  149. engine.logger.Error(err)
  150. continue
  151. }
  152. val = bytes
  153. }
  154. } else {
  155. engine.autoMapType(fieldValue)
  156. if table, ok := engine.Tables[fieldValue.Type()]; ok {
  157. if len(table.PrimaryKeys) == 1 {
  158. pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
  159. // fix non-int pk issues
  160. //if pkField.Int() != 0 {
  161. if pkField.IsValid() && !utils.IsZero(pkField.Interface()) {
  162. val = pkField.Interface()
  163. } else {
  164. continue
  165. }
  166. } else {
  167. //TODO: how to handler?
  168. return nil, fmt.Errorf("not supported %v as %v", fieldValue.Interface(), table.PrimaryKeys)
  169. }
  170. } else {
  171. val = fieldValue.Interface()
  172. }
  173. }
  174. }
  175. case reflect.Array:
  176. continue
  177. case reflect.Slice, reflect.Map:
  178. if fieldValue == reflect.Zero(fieldType) {
  179. continue
  180. }
  181. if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
  182. continue
  183. }
  184. if col.SQLType.IsText() {
  185. bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface())
  186. if err != nil {
  187. engine.logger.Error(err)
  188. continue
  189. }
  190. val = string(bytes)
  191. } else if col.SQLType.IsBlob() {
  192. var bytes []byte
  193. var err error
  194. if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
  195. fieldType.Elem().Kind() == reflect.Uint8 {
  196. if fieldValue.Len() > 0 {
  197. val = fieldValue.Bytes()
  198. } else {
  199. continue
  200. }
  201. } else {
  202. bytes, err = DefaultJSONHandler.Marshal(fieldValue.Interface())
  203. if err != nil {
  204. engine.logger.Error(err)
  205. continue
  206. }
  207. val = bytes
  208. }
  209. } else {
  210. continue
  211. }
  212. default:
  213. val = fieldValue.Interface()
  214. }
  215. conds = append(conds, builder.Eq{colName: val})
  216. }
  217. return builder.And(conds...), nil
  218. }