session_convert.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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"
  7. "database/sql/driver"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "reflect"
  12. "strconv"
  13. "strings"
  14. "time"
  15. "github.com/xormplus/core"
  16. )
  17. func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) {
  18. sdata := strings.TrimSpace(data)
  19. var x time.Time
  20. var err error
  21. var parseLoc = session.engine.DatabaseTZ
  22. if col.TimeZone != nil {
  23. parseLoc = col.TimeZone
  24. }
  25. if sdata == zeroTime0 || sdata == zeroTime1 {
  26. } else if !strings.ContainsAny(sdata, "- :") { // !nashtsai! has only found that mymysql driver is using this for time type column
  27. // time stamp
  28. sd, err := strconv.ParseInt(sdata, 10, 64)
  29. if err == nil {
  30. x = time.Unix(sd, 0)
  31. session.engine.logger.Debugf("time(0) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  32. } else {
  33. session.engine.logger.Debugf("time(0) err key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  34. }
  35. } else if len(sdata) > 19 && strings.Contains(sdata, "-") {
  36. x, err = time.ParseInLocation(time.RFC3339Nano, sdata, parseLoc)
  37. session.engine.logger.Debugf("time(1) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  38. if err != nil {
  39. x, err = time.ParseInLocation("2006-01-02 15:04:05.999999999", sdata, parseLoc)
  40. session.engine.logger.Debugf("time(2) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  41. }
  42. if err != nil {
  43. x, err = time.ParseInLocation("2006-01-02 15:04:05.9999999 Z07:00", sdata, parseLoc)
  44. session.engine.logger.Debugf("time(3) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  45. }
  46. } else if len(sdata) == 19 && strings.Contains(sdata, "-") {
  47. x, err = time.ParseInLocation("2006-01-02 15:04:05", sdata, parseLoc)
  48. session.engine.logger.Debugf("time(4) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  49. } else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' {
  50. x, err = time.ParseInLocation("2006-01-02", sdata, parseLoc)
  51. session.engine.logger.Debugf("time(5) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  52. } else if col.SQLType.Name == core.Time {
  53. if strings.Contains(sdata, " ") {
  54. ssd := strings.Split(sdata, " ")
  55. sdata = ssd[1]
  56. }
  57. sdata = strings.TrimSpace(sdata)
  58. if session.engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 {
  59. sdata = sdata[len(sdata)-8:]
  60. }
  61. st := fmt.Sprintf("2006-01-02 %v", sdata)
  62. x, err = time.ParseInLocation("2006-01-02 15:04:05", st, parseLoc)
  63. session.engine.logger.Debugf("time(6) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  64. } else {
  65. outErr = fmt.Errorf("unsupported time format %v", sdata)
  66. return
  67. }
  68. if err != nil {
  69. outErr = fmt.Errorf("unsupported time format %v: %v", sdata, err)
  70. return
  71. }
  72. outTime = x.In(session.engine.TZLocation)
  73. return
  74. }
  75. func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.Time, outErr error) {
  76. return session.str2Time(col, string(data))
  77. }
  78. // convert a db data([]byte) to a field value
  79. func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, data []byte) error {
  80. if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  81. return structConvert.FromDB(data)
  82. }
  83. if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
  84. return structConvert.FromDB(data)
  85. }
  86. var v interface{}
  87. key := col.Name
  88. fieldType := fieldValue.Type()
  89. switch fieldType.Kind() {
  90. case reflect.Complex64, reflect.Complex128:
  91. x := reflect.New(fieldType)
  92. if len(data) > 0 {
  93. err := json.Unmarshal(data, x.Interface())
  94. if err != nil {
  95. session.engine.logger.Error(err)
  96. return err
  97. }
  98. fieldValue.Set(x.Elem())
  99. }
  100. case reflect.Slice, reflect.Array, reflect.Map:
  101. v = data
  102. t := fieldType.Elem()
  103. k := t.Kind()
  104. if col.SQLType.IsText() {
  105. x := reflect.New(fieldType)
  106. if len(data) > 0 {
  107. err := json.Unmarshal(data, x.Interface())
  108. if err != nil {
  109. session.engine.logger.Error(err)
  110. return err
  111. }
  112. fieldValue.Set(x.Elem())
  113. }
  114. } else if col.SQLType.IsBlob() {
  115. if k == reflect.Uint8 {
  116. fieldValue.Set(reflect.ValueOf(v))
  117. } else {
  118. x := reflect.New(fieldType)
  119. if len(data) > 0 {
  120. err := json.Unmarshal(data, x.Interface())
  121. if err != nil {
  122. session.engine.logger.Error(err)
  123. return err
  124. }
  125. fieldValue.Set(x.Elem())
  126. }
  127. }
  128. } else {
  129. return ErrUnSupportedType
  130. }
  131. case reflect.String:
  132. fieldValue.SetString(string(data))
  133. case reflect.Bool:
  134. d := string(data)
  135. v, err := strconv.ParseBool(d)
  136. if err != nil {
  137. return fmt.Errorf("arg %v as bool: %s", key, err.Error())
  138. }
  139. fieldValue.Set(reflect.ValueOf(v))
  140. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  141. sdata := string(data)
  142. var x int64
  143. var err error
  144. // for mysql, when use bit, it returned \x01
  145. if col.SQLType.Name == core.Bit &&
  146. session.engine.dialect.DBType() == core.MYSQL { // !nashtsai! TODO dialect needs to provide conversion interface API
  147. if len(data) == 1 {
  148. x = int64(data[0])
  149. } else {
  150. x = 0
  151. }
  152. } else if strings.HasPrefix(sdata, "0x") {
  153. x, err = strconv.ParseInt(sdata, 16, 64)
  154. } else if strings.HasPrefix(sdata, "0") {
  155. x, err = strconv.ParseInt(sdata, 8, 64)
  156. } else if strings.EqualFold(sdata, "true") {
  157. x = 1
  158. } else if strings.EqualFold(sdata, "false") {
  159. x = 0
  160. } else {
  161. x, err = strconv.ParseInt(sdata, 10, 64)
  162. }
  163. if err != nil {
  164. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  165. }
  166. fieldValue.SetInt(x)
  167. case reflect.Float32, reflect.Float64:
  168. x, err := strconv.ParseFloat(string(data), 64)
  169. if err != nil {
  170. return fmt.Errorf("arg %v as float64: %s", key, err.Error())
  171. }
  172. fieldValue.SetFloat(x)
  173. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  174. x, err := strconv.ParseUint(string(data), 10, 64)
  175. if err != nil {
  176. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  177. }
  178. fieldValue.SetUint(x)
  179. //Currently only support Time type
  180. case reflect.Struct:
  181. // !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
  182. if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
  183. if err := nulVal.Scan(data); err != nil {
  184. return fmt.Errorf("sql.Scan(%v) failed: %s ", data, err.Error())
  185. }
  186. } else {
  187. if fieldType.ConvertibleTo(core.TimeType) {
  188. x, err := session.byte2Time(col, data)
  189. if err != nil {
  190. return err
  191. }
  192. v = x
  193. fieldValue.Set(reflect.ValueOf(v).Convert(fieldType))
  194. } else if session.statement.UseCascade {
  195. table, err := session.engine.autoMapType(*fieldValue)
  196. if err != nil {
  197. return err
  198. }
  199. // TODO: current only support 1 primary key
  200. if len(table.PrimaryKeys) > 1 {
  201. return errors.New("unsupported composited primary key cascade")
  202. }
  203. var pk = make(core.PK, len(table.PrimaryKeys))
  204. rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
  205. pk[0], err = str2PK(string(data), rawValueType)
  206. if err != nil {
  207. return err
  208. }
  209. if !isPKZero(pk) {
  210. // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
  211. // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
  212. // property to be fetched lazily
  213. structInter := reflect.New(fieldValue.Type())
  214. has, err := session.ID(pk).NoCascade().get(structInter.Interface())
  215. if err != nil {
  216. return err
  217. }
  218. if has {
  219. v = structInter.Elem().Interface()
  220. fieldValue.Set(reflect.ValueOf(v))
  221. } else {
  222. return errors.New("cascade obj is not exist")
  223. }
  224. }
  225. }
  226. }
  227. case reflect.Ptr:
  228. // !nashtsai! TODO merge duplicated codes above
  229. //typeStr := fieldType.String()
  230. switch fieldType.Elem().Kind() {
  231. // case "*string":
  232. case core.StringType.Kind():
  233. x := string(data)
  234. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  235. // case "*bool":
  236. case core.BoolType.Kind():
  237. d := string(data)
  238. v, err := strconv.ParseBool(d)
  239. if err != nil {
  240. return fmt.Errorf("arg %v as bool: %s", key, err.Error())
  241. }
  242. fieldValue.Set(reflect.ValueOf(&v).Convert(fieldType))
  243. // case "*complex64":
  244. case core.Complex64Type.Kind():
  245. var x complex64
  246. if len(data) > 0 {
  247. err := json.Unmarshal(data, &x)
  248. if err != nil {
  249. session.engine.logger.Error(err)
  250. return err
  251. }
  252. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  253. }
  254. // case "*complex128":
  255. case core.Complex128Type.Kind():
  256. var x complex128
  257. if len(data) > 0 {
  258. err := json.Unmarshal(data, &x)
  259. if err != nil {
  260. session.engine.logger.Error(err)
  261. return err
  262. }
  263. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  264. }
  265. // case "*float64":
  266. case core.Float64Type.Kind():
  267. x, err := strconv.ParseFloat(string(data), 64)
  268. if err != nil {
  269. return fmt.Errorf("arg %v as float64: %s", key, err.Error())
  270. }
  271. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  272. // case "*float32":
  273. case core.Float32Type.Kind():
  274. var x float32
  275. x1, err := strconv.ParseFloat(string(data), 32)
  276. if err != nil {
  277. return fmt.Errorf("arg %v as float32: %s", key, err.Error())
  278. }
  279. x = float32(x1)
  280. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  281. // case "*uint64":
  282. case core.Uint64Type.Kind():
  283. var x uint64
  284. x, err := strconv.ParseUint(string(data), 10, 64)
  285. if err != nil {
  286. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  287. }
  288. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  289. // case "*uint":
  290. case core.UintType.Kind():
  291. var x uint
  292. x1, err := strconv.ParseUint(string(data), 10, 64)
  293. if err != nil {
  294. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  295. }
  296. x = uint(x1)
  297. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  298. // case "*uint32":
  299. case core.Uint32Type.Kind():
  300. var x uint32
  301. x1, err := strconv.ParseUint(string(data), 10, 64)
  302. if err != nil {
  303. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  304. }
  305. x = uint32(x1)
  306. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  307. // case "*uint8":
  308. case core.Uint8Type.Kind():
  309. var x uint8
  310. x1, err := strconv.ParseUint(string(data), 10, 64)
  311. if err != nil {
  312. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  313. }
  314. x = uint8(x1)
  315. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  316. // case "*uint16":
  317. case core.Uint16Type.Kind():
  318. var x uint16
  319. x1, err := strconv.ParseUint(string(data), 10, 64)
  320. if err != nil {
  321. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  322. }
  323. x = uint16(x1)
  324. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  325. // case "*int64":
  326. case core.Int64Type.Kind():
  327. sdata := string(data)
  328. var x int64
  329. var err error
  330. // for mysql, when use bit, it returned \x01
  331. if col.SQLType.Name == core.Bit &&
  332. strings.Contains(session.engine.DriverName(), "mysql") {
  333. if len(data) == 1 {
  334. x = int64(data[0])
  335. } else {
  336. x = 0
  337. }
  338. } else if strings.HasPrefix(sdata, "0x") {
  339. x, err = strconv.ParseInt(sdata, 16, 64)
  340. } else if strings.HasPrefix(sdata, "0") {
  341. x, err = strconv.ParseInt(sdata, 8, 64)
  342. } else {
  343. x, err = strconv.ParseInt(sdata, 10, 64)
  344. }
  345. if err != nil {
  346. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  347. }
  348. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  349. // case "*int":
  350. case core.IntType.Kind():
  351. sdata := string(data)
  352. var x int
  353. var x1 int64
  354. var err error
  355. // for mysql, when use bit, it returned \x01
  356. if col.SQLType.Name == core.Bit &&
  357. strings.Contains(session.engine.DriverName(), "mysql") {
  358. if len(data) == 1 {
  359. x = int(data[0])
  360. } else {
  361. x = 0
  362. }
  363. } else if strings.HasPrefix(sdata, "0x") {
  364. x1, err = strconv.ParseInt(sdata, 16, 64)
  365. x = int(x1)
  366. } else if strings.HasPrefix(sdata, "0") {
  367. x1, err = strconv.ParseInt(sdata, 8, 64)
  368. x = int(x1)
  369. } else {
  370. x1, err = strconv.ParseInt(sdata, 10, 64)
  371. x = int(x1)
  372. }
  373. if err != nil {
  374. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  375. }
  376. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  377. // case "*int32":
  378. case core.Int32Type.Kind():
  379. sdata := string(data)
  380. var x int32
  381. var x1 int64
  382. var err error
  383. // for mysql, when use bit, it returned \x01
  384. if col.SQLType.Name == core.Bit &&
  385. session.engine.dialect.DBType() == core.MYSQL {
  386. if len(data) == 1 {
  387. x = int32(data[0])
  388. } else {
  389. x = 0
  390. }
  391. } else if strings.HasPrefix(sdata, "0x") {
  392. x1, err = strconv.ParseInt(sdata, 16, 64)
  393. x = int32(x1)
  394. } else if strings.HasPrefix(sdata, "0") {
  395. x1, err = strconv.ParseInt(sdata, 8, 64)
  396. x = int32(x1)
  397. } else {
  398. x1, err = strconv.ParseInt(sdata, 10, 64)
  399. x = int32(x1)
  400. }
  401. if err != nil {
  402. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  403. }
  404. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  405. // case "*int8":
  406. case core.Int8Type.Kind():
  407. sdata := string(data)
  408. var x int8
  409. var x1 int64
  410. var err error
  411. // for mysql, when use bit, it returned \x01
  412. if col.SQLType.Name == core.Bit &&
  413. strings.Contains(session.engine.DriverName(), "mysql") {
  414. if len(data) == 1 {
  415. x = int8(data[0])
  416. } else {
  417. x = 0
  418. }
  419. } else if strings.HasPrefix(sdata, "0x") {
  420. x1, err = strconv.ParseInt(sdata, 16, 64)
  421. x = int8(x1)
  422. } else if strings.HasPrefix(sdata, "0") {
  423. x1, err = strconv.ParseInt(sdata, 8, 64)
  424. x = int8(x1)
  425. } else {
  426. x1, err = strconv.ParseInt(sdata, 10, 64)
  427. x = int8(x1)
  428. }
  429. if err != nil {
  430. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  431. }
  432. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  433. // case "*int16":
  434. case core.Int16Type.Kind():
  435. sdata := string(data)
  436. var x int16
  437. var x1 int64
  438. var err error
  439. // for mysql, when use bit, it returned \x01
  440. if col.SQLType.Name == core.Bit &&
  441. strings.Contains(session.engine.DriverName(), "mysql") {
  442. if len(data) == 1 {
  443. x = int16(data[0])
  444. } else {
  445. x = 0
  446. }
  447. } else if strings.HasPrefix(sdata, "0x") {
  448. x1, err = strconv.ParseInt(sdata, 16, 64)
  449. x = int16(x1)
  450. } else if strings.HasPrefix(sdata, "0") {
  451. x1, err = strconv.ParseInt(sdata, 8, 64)
  452. x = int16(x1)
  453. } else {
  454. x1, err = strconv.ParseInt(sdata, 10, 64)
  455. x = int16(x1)
  456. }
  457. if err != nil {
  458. return fmt.Errorf("arg %v as int: %s", key, err.Error())
  459. }
  460. fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  461. // case "*SomeStruct":
  462. case reflect.Struct:
  463. switch fieldType {
  464. // case "*.time.Time":
  465. case core.PtrTimeType:
  466. x, err := session.byte2Time(col, data)
  467. if err != nil {
  468. return err
  469. }
  470. v = x
  471. fieldValue.Set(reflect.ValueOf(&x))
  472. default:
  473. if session.statement.UseCascade {
  474. structInter := reflect.New(fieldType.Elem())
  475. table, err := session.engine.autoMapType(structInter.Elem())
  476. if err != nil {
  477. return err
  478. }
  479. if len(table.PrimaryKeys) > 1 {
  480. return errors.New("unsupported composited primary key cascade")
  481. }
  482. var pk = make(core.PK, len(table.PrimaryKeys))
  483. rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
  484. pk[0], err = str2PK(string(data), rawValueType)
  485. if err != nil {
  486. return err
  487. }
  488. if !isPKZero(pk) {
  489. // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
  490. // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
  491. // property to be fetched lazily
  492. has, err := session.ID(pk).NoCascade().get(structInter.Interface())
  493. if err != nil {
  494. return err
  495. }
  496. if has {
  497. v = structInter.Interface()
  498. fieldValue.Set(reflect.ValueOf(v))
  499. } else {
  500. return errors.New("cascade obj is not exist")
  501. }
  502. }
  503. } else {
  504. return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
  505. }
  506. }
  507. default:
  508. return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
  509. }
  510. default:
  511. return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
  512. }
  513. return nil
  514. }
  515. // convert a field value of a struct to interface for put into db
  516. func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) {
  517. if fieldValue.CanAddr() {
  518. if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  519. data, err := fieldConvert.ToDB()
  520. if err != nil {
  521. return 0, err
  522. }
  523. if col.SQLType.IsBlob() {
  524. return data, nil
  525. }
  526. return string(data), nil
  527. }
  528. }
  529. if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok {
  530. data, err := fieldConvert.ToDB()
  531. if err != nil {
  532. return 0, err
  533. }
  534. if col.SQLType.IsBlob() {
  535. return data, nil
  536. }
  537. return string(data), nil
  538. }
  539. fieldType := fieldValue.Type()
  540. k := fieldType.Kind()
  541. if k == reflect.Ptr {
  542. if fieldValue.IsNil() {
  543. return nil, nil
  544. } else if !fieldValue.IsValid() {
  545. session.engine.logger.Warn("the field[", col.FieldName, "] is invalid")
  546. return nil, nil
  547. } else {
  548. // !nashtsai! deference pointer type to instance type
  549. fieldValue = fieldValue.Elem()
  550. fieldType = fieldValue.Type()
  551. k = fieldType.Kind()
  552. }
  553. }
  554. switch k {
  555. case reflect.Bool:
  556. return fieldValue.Bool(), nil
  557. case reflect.String:
  558. return fieldValue.String(), nil
  559. case reflect.Struct:
  560. if fieldType.ConvertibleTo(core.TimeType) {
  561. t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
  562. tf := session.engine.formatColTime(col, t)
  563. return tf, nil
  564. }
  565. if !col.SQLType.IsJson() {
  566. // !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
  567. if v, ok := fieldValue.Interface().(driver.Valuer); ok {
  568. return v.Value()
  569. }
  570. fieldTable, err := session.engine.autoMapType(fieldValue)
  571. if err != nil {
  572. return nil, err
  573. }
  574. if len(fieldTable.PrimaryKeys) == 1 {
  575. pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
  576. return pkField.Interface(), nil
  577. }
  578. return 0, fmt.Errorf("no primary key for col %v", col.Name)
  579. }
  580. if col.SQLType.IsText() {
  581. bytes, err := json.Marshal(fieldValue.Interface())
  582. if err != nil {
  583. session.engine.logger.Error(err)
  584. return 0, err
  585. }
  586. return string(bytes), nil
  587. } else if col.SQLType.IsBlob() {
  588. bytes, err := json.Marshal(fieldValue.Interface())
  589. if err != nil {
  590. session.engine.logger.Error(err)
  591. return 0, err
  592. }
  593. return bytes, nil
  594. }
  595. return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
  596. case reflect.Complex64, reflect.Complex128:
  597. bytes, err := json.Marshal(fieldValue.Interface())
  598. if err != nil {
  599. session.engine.logger.Error(err)
  600. return 0, err
  601. }
  602. return string(bytes), nil
  603. case reflect.Array, reflect.Slice, reflect.Map:
  604. if !fieldValue.IsValid() {
  605. return fieldValue.Interface(), nil
  606. }
  607. if col.SQLType.IsText() {
  608. bytes, err := json.Marshal(fieldValue.Interface())
  609. if err != nil {
  610. session.engine.logger.Error(err)
  611. return 0, err
  612. }
  613. return string(bytes), nil
  614. } else if col.SQLType.IsBlob() {
  615. var bytes []byte
  616. var err error
  617. if (k == reflect.Array || k == reflect.Slice) &&
  618. (fieldValue.Type().Elem().Kind() == reflect.Uint8) {
  619. bytes = fieldValue.Bytes()
  620. } else {
  621. bytes, err = json.Marshal(fieldValue.Interface())
  622. if err != nil {
  623. session.engine.logger.Error(err)
  624. return 0, err
  625. }
  626. }
  627. return bytes, nil
  628. }
  629. return nil, ErrUnSupportedType
  630. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  631. return int64(fieldValue.Uint()), nil
  632. default:
  633. return fieldValue.Interface(), nil
  634. }
  635. }