THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

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.

405 lines
7.3KB

  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. "errors"
  9. "fmt"
  10. "strconv"
  11. "strings"
  12. "testing"
  13. "github.com/stretchr/testify/assert"
  14. )
  15. type NullType struct {
  16. Id int `xorm:"pk autoincr"`
  17. Name sql.NullString
  18. Age sql.NullInt64
  19. Height sql.NullFloat64
  20. IsMan sql.NullBool `xorm:"null"`
  21. CustomStruct CustomStruct `xorm:"valchar(64) null"`
  22. }
  23. type CustomStruct struct {
  24. Year int
  25. Month int
  26. Day int
  27. }
  28. func (CustomStruct) String() string {
  29. return "CustomStruct"
  30. }
  31. func (m *CustomStruct) Scan(value interface{}) error {
  32. if value == nil {
  33. m.Year, m.Month, m.Day = 0, 0, 0
  34. return nil
  35. }
  36. if s, ok := value.([]byte); ok {
  37. seps := strings.Split(string(s), "/")
  38. m.Year, _ = strconv.Atoi(seps[0])
  39. m.Month, _ = strconv.Atoi(seps[1])
  40. m.Day, _ = strconv.Atoi(seps[2])
  41. return nil
  42. }
  43. return errors.New("scan data not fit []byte")
  44. }
  45. func (m CustomStruct) Value() (driver.Value, error) {
  46. return fmt.Sprintf("%d/%d/%d", m.Year, m.Month, m.Day), nil
  47. }
  48. func TestCreateNullStructTable(t *testing.T) {
  49. assert.NoError(t, prepareEngine())
  50. err := testEngine.CreateTables(new(NullType))
  51. if err != nil {
  52. t.Error(err)
  53. panic(err)
  54. }
  55. }
  56. func TestDropNullStructTable(t *testing.T) {
  57. assert.NoError(t, prepareEngine())
  58. err := testEngine.DropTables(new(NullType))
  59. if err != nil {
  60. t.Error(err)
  61. panic(err)
  62. }
  63. }
  64. func TestNullStructInsert(t *testing.T) {
  65. assert.NoError(t, prepareEngine())
  66. assertSync(t, new(NullType))
  67. if true {
  68. item := new(NullType)
  69. _, err := testEngine.Insert(item)
  70. if err != nil {
  71. t.Error(err)
  72. panic(err)
  73. }
  74. fmt.Println(item)
  75. if item.Id != 1 {
  76. err = errors.New("insert error")
  77. t.Error(err)
  78. panic(err)
  79. }
  80. }
  81. if true {
  82. item := NullType{
  83. Name: sql.NullString{"haolei", true},
  84. Age: sql.NullInt64{34, true},
  85. Height: sql.NullFloat64{1.72, true},
  86. IsMan: sql.NullBool{true, true},
  87. }
  88. _, err := testEngine.Insert(&item)
  89. if err != nil {
  90. t.Error(err)
  91. panic(err)
  92. }
  93. fmt.Println(item)
  94. if item.Id != 2 {
  95. err = errors.New("insert error")
  96. t.Error(err)
  97. panic(err)
  98. }
  99. }
  100. if true {
  101. items := []NullType{}
  102. for i := 0; i < 5; i++ {
  103. item := NullType{
  104. Name: sql.NullString{"haolei_" + fmt.Sprint(i+1), true},
  105. Age: sql.NullInt64{30 + int64(i), true},
  106. Height: sql.NullFloat64{1.5 + 1.1*float64(i), true},
  107. IsMan: sql.NullBool{true, true},
  108. CustomStruct: CustomStruct{i, i + 1, i + 2},
  109. }
  110. items = append(items, item)
  111. }
  112. _, err := testEngine.Insert(&items)
  113. if err != nil {
  114. t.Error(err)
  115. panic(err)
  116. }
  117. fmt.Println(items)
  118. }
  119. }
  120. func TestNullStructUpdate(t *testing.T) {
  121. assert.NoError(t, prepareEngine())
  122. assertSync(t, new(NullType))
  123. _, err := testEngine.Insert([]NullType{
  124. {
  125. Name: sql.NullString{
  126. String: "name1",
  127. Valid: true,
  128. },
  129. },
  130. {
  131. Name: sql.NullString{
  132. String: "name2",
  133. Valid: true,
  134. },
  135. },
  136. {
  137. Name: sql.NullString{
  138. String: "name3",
  139. Valid: true,
  140. },
  141. },
  142. {
  143. Name: sql.NullString{
  144. String: "name4",
  145. Valid: true,
  146. },
  147. },
  148. })
  149. assert.NoError(t, err)
  150. if true { // 测试可插入NULL
  151. item := new(NullType)
  152. item.Age = sql.NullInt64{23, true}
  153. item.Height = sql.NullFloat64{0, false} // update to NULL
  154. affected, err := testEngine.ID(2).Cols("age", "height", "is_man").Update(item)
  155. if err != nil {
  156. t.Error(err)
  157. panic(err)
  158. }
  159. if affected != 1 {
  160. err := errors.New("update failed")
  161. t.Error(err)
  162. panic(err)
  163. }
  164. }
  165. if true { // 测试In update
  166. item := new(NullType)
  167. item.Age = sql.NullInt64{23, true}
  168. affected, err := testEngine.In("id", 3, 4).Cols("age", "height", "is_man").Update(item)
  169. if err != nil {
  170. t.Error(err)
  171. panic(err)
  172. }
  173. if affected != 2 {
  174. err := errors.New("update failed")
  175. t.Error(err)
  176. panic(err)
  177. }
  178. }
  179. if true { // 测试where
  180. item := new(NullType)
  181. item.Name = sql.NullString{"nullname", true}
  182. item.IsMan = sql.NullBool{true, true}
  183. item.Age = sql.NullInt64{34, true}
  184. _, err := testEngine.Where("age > ?", 34).Update(item)
  185. if err != nil {
  186. t.Error(err)
  187. panic(err)
  188. }
  189. }
  190. if true { // 修改全部时,插入空值
  191. item := &NullType{
  192. Name: sql.NullString{"winxxp", true},
  193. Age: sql.NullInt64{30, true},
  194. Height: sql.NullFloat64{1.72, true},
  195. // IsMan: sql.NullBool{true, true},
  196. }
  197. _, err := testEngine.AllCols().ID(6).Update(item)
  198. if err != nil {
  199. t.Error(err)
  200. panic(err)
  201. }
  202. fmt.Println(item)
  203. }
  204. }
  205. func TestNullStructFind(t *testing.T) {
  206. assert.NoError(t, prepareEngine())
  207. assertSync(t, new(NullType))
  208. _, err := testEngine.Insert([]NullType{
  209. {
  210. Name: sql.NullString{
  211. String: "name1",
  212. Valid: false,
  213. },
  214. },
  215. {
  216. Name: sql.NullString{
  217. String: "name2",
  218. Valid: true,
  219. },
  220. },
  221. {
  222. Name: sql.NullString{
  223. String: "name3",
  224. Valid: true,
  225. },
  226. },
  227. {
  228. Name: sql.NullString{
  229. String: "name4",
  230. Valid: true,
  231. },
  232. },
  233. })
  234. assert.NoError(t, err)
  235. if true {
  236. item := new(NullType)
  237. has, err := testEngine.ID(1).Get(item)
  238. if err != nil {
  239. t.Error(err)
  240. panic(err)
  241. }
  242. if !has {
  243. t.Error(errors.New("no find id 1"))
  244. panic(err)
  245. }
  246. fmt.Println(item)
  247. if item.Id != 1 || item.Name.Valid || item.Age.Valid || item.Height.Valid ||
  248. item.IsMan.Valid {
  249. err = errors.New("insert error")
  250. t.Error(err)
  251. panic(err)
  252. }
  253. }
  254. if true {
  255. item := new(NullType)
  256. item.Id = 2
  257. has, err := testEngine.Get(item)
  258. if err != nil {
  259. t.Error(err)
  260. panic(err)
  261. }
  262. if !has {
  263. t.Error(errors.New("no find id 2"))
  264. panic(err)
  265. }
  266. fmt.Println(item)
  267. }
  268. if true {
  269. item := make([]NullType, 0)
  270. err := testEngine.ID(2).Find(&item)
  271. if err != nil {
  272. t.Error(err)
  273. panic(err)
  274. }
  275. fmt.Println(item)
  276. }
  277. if true {
  278. item := make([]NullType, 0)
  279. err := testEngine.Asc("age").Find(&item)
  280. if err != nil {
  281. t.Error(err)
  282. panic(err)
  283. }
  284. for k, v := range item {
  285. fmt.Println(k, v)
  286. }
  287. }
  288. }
  289. func TestNullStructIterate(t *testing.T) {
  290. assert.NoError(t, prepareEngine())
  291. assertSync(t, new(NullType))
  292. if true {
  293. err := testEngine.Where("age IS NOT NULL").OrderBy("age").Iterate(new(NullType),
  294. func(i int, bean interface{}) error {
  295. nultype := bean.(*NullType)
  296. fmt.Println(i, nultype)
  297. return nil
  298. })
  299. if err != nil {
  300. t.Error(err)
  301. panic(err)
  302. }
  303. }
  304. }
  305. func TestNullStructCount(t *testing.T) {
  306. assert.NoError(t, prepareEngine())
  307. assertSync(t, new(NullType))
  308. if true {
  309. item := new(NullType)
  310. total, err := testEngine.Where("age IS NOT NULL").Count(item)
  311. if err != nil {
  312. t.Error(err)
  313. panic(err)
  314. }
  315. fmt.Println(total)
  316. }
  317. }
  318. func TestNullStructRows(t *testing.T) {
  319. assert.NoError(t, prepareEngine())
  320. assertSync(t, new(NullType))
  321. item := new(NullType)
  322. rows, err := testEngine.Where("id > ?", 1).Rows(item)
  323. if err != nil {
  324. t.Error(err)
  325. panic(err)
  326. }
  327. defer rows.Close()
  328. for rows.Next() {
  329. err = rows.Scan(item)
  330. if err != nil {
  331. t.Error(err)
  332. panic(err)
  333. }
  334. fmt.Println(item)
  335. }
  336. }
  337. func TestNullStructDelete(t *testing.T) {
  338. assert.NoError(t, prepareEngine())
  339. assertSync(t, new(NullType))
  340. item := new(NullType)
  341. _, err := testEngine.ID(1).Delete(item)
  342. if err != nil {
  343. t.Error(err)
  344. panic(err)
  345. }
  346. _, err = testEngine.Where("id > ?", 1).Delete(item)
  347. if err != nil {
  348. t.Error(err)
  349. panic(err)
  350. }
  351. }