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