main_test.go 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. package gorm_test
  2. import (
  3. "database/sql"
  4. "database/sql/driver"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "reflect"
  9. "strconv"
  10. "strings"
  11. "testing"
  12. "time"
  13. "github.com/erikstmartin/go-testdb"
  14. "github.com/jinzhu/gorm"
  15. _ "github.com/jinzhu/gorm/dialects/mssql"
  16. _ "github.com/jinzhu/gorm/dialects/mysql"
  17. "github.com/jinzhu/gorm/dialects/postgres"
  18. _ "github.com/jinzhu/gorm/dialects/sqlite"
  19. "github.com/jinzhu/now"
  20. )
  21. var (
  22. DB *gorm.DB
  23. t1, t2, t3, t4, t5 time.Time
  24. )
  25. func init() {
  26. var err error
  27. if DB, err = OpenTestConnection(); err != nil {
  28. panic(fmt.Sprintf("No error should happen when connecting to test database, but got err=%+v", err))
  29. }
  30. runMigration()
  31. }
  32. func OpenTestConnection() (db *gorm.DB, err error) {
  33. dbDSN := os.Getenv("GORM_DSN")
  34. switch os.Getenv("GORM_DIALECT") {
  35. case "mysql":
  36. fmt.Println("testing mysql...")
  37. if dbDSN == "" {
  38. dbDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True"
  39. }
  40. db, err = gorm.Open("mysql", dbDSN)
  41. case "postgres":
  42. fmt.Println("testing postgres...")
  43. if dbDSN == "" {
  44. dbDSN = "user=gorm password=gorm DB.name=gorm port=9920 sslmode=disable"
  45. }
  46. db, err = gorm.Open("postgres", dbDSN)
  47. case "mssql":
  48. // CREATE LOGIN gorm WITH PASSWORD = 'LoremIpsum86';
  49. // CREATE DATABASE gorm;
  50. // USE gorm;
  51. // CREATE USER gorm FROM LOGIN gorm;
  52. // sp_changedbowner 'gorm';
  53. fmt.Println("testing mssql...")
  54. if dbDSN == "" {
  55. dbDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
  56. }
  57. db, err = gorm.Open("mssql", dbDSN)
  58. default:
  59. fmt.Println("testing sqlite3...")
  60. db, err = gorm.Open("sqlite3", filepath.Join(os.TempDir(), "gorm.db"))
  61. }
  62. // db.SetLogger(Logger{log.New(os.Stdout, "\r\n", 0)})
  63. // db.SetLogger(log.New(os.Stdout, "\r\n", 0))
  64. if debug := os.Getenv("DEBUG"); debug == "true" {
  65. db.LogMode(true)
  66. } else if debug == "false" {
  67. db.LogMode(false)
  68. }
  69. db.DB().SetMaxIdleConns(10)
  70. return
  71. }
  72. func TestOpen_ReturnsError_WithBadArgs(t *testing.T) {
  73. stringRef := "foo"
  74. testCases := []interface{}{42, time.Now(), &stringRef}
  75. for _, tc := range testCases {
  76. t.Run(fmt.Sprintf("%v", tc), func(t *testing.T) {
  77. _, err := gorm.Open("postgresql", tc)
  78. if err == nil {
  79. t.Error("Should got error with invalid database source")
  80. }
  81. if !strings.HasPrefix(err.Error(), "invalid database source:") {
  82. t.Errorf("Should got error starting with \"invalid database source:\", but got %q", err.Error())
  83. }
  84. })
  85. }
  86. }
  87. func TestStringPrimaryKey(t *testing.T) {
  88. type UUIDStruct struct {
  89. ID string `gorm:"primary_key"`
  90. Name string
  91. }
  92. DB.DropTable(&UUIDStruct{})
  93. DB.AutoMigrate(&UUIDStruct{})
  94. data := UUIDStruct{ID: "uuid", Name: "hello"}
  95. if err := DB.Save(&data).Error; err != nil || data.ID != "uuid" || data.Name != "hello" {
  96. t.Errorf("string primary key should not be populated")
  97. }
  98. data = UUIDStruct{ID: "uuid", Name: "hello world"}
  99. if err := DB.Save(&data).Error; err != nil || data.ID != "uuid" || data.Name != "hello world" {
  100. t.Errorf("string primary key should not be populated")
  101. }
  102. }
  103. func TestExceptionsWithInvalidSql(t *testing.T) {
  104. var columns []string
  105. if DB.Where("sdsd.zaaa = ?", "sd;;;aa").Pluck("aaa", &columns).Error == nil {
  106. t.Errorf("Should got error with invalid SQL")
  107. }
  108. if DB.Model(&User{}).Where("sdsd.zaaa = ?", "sd;;;aa").Pluck("aaa", &columns).Error == nil {
  109. t.Errorf("Should got error with invalid SQL")
  110. }
  111. if DB.Where("sdsd.zaaa = ?", "sd;;;aa").Find(&User{}).Error == nil {
  112. t.Errorf("Should got error with invalid SQL")
  113. }
  114. var count1, count2 int64
  115. DB.Model(&User{}).Count(&count1)
  116. if count1 <= 0 {
  117. t.Errorf("Should find some users")
  118. }
  119. if DB.Where("name = ?", "jinzhu; delete * from users").First(&User{}).Error == nil {
  120. t.Errorf("Should got error with invalid SQL")
  121. }
  122. DB.Model(&User{}).Count(&count2)
  123. if count1 != count2 {
  124. t.Errorf("No user should not be deleted by invalid SQL")
  125. }
  126. }
  127. func TestSetTable(t *testing.T) {
  128. DB.Create(getPreparedUser("pluck_user1", "pluck_user"))
  129. DB.Create(getPreparedUser("pluck_user2", "pluck_user"))
  130. DB.Create(getPreparedUser("pluck_user3", "pluck_user"))
  131. if err := DB.Table("users").Where("role = ?", "pluck_user").Pluck("age", &[]int{}).Error; err != nil {
  132. t.Error("No errors should happen if set table for pluck", err)
  133. }
  134. var users []User
  135. if DB.Table("users").Find(&[]User{}).Error != nil {
  136. t.Errorf("No errors should happen if set table for find")
  137. }
  138. if DB.Table("invalid_table").Find(&users).Error == nil {
  139. t.Errorf("Should got error when table is set to an invalid table")
  140. }
  141. DB.Exec("drop table deleted_users;")
  142. if DB.Table("deleted_users").CreateTable(&User{}).Error != nil {
  143. t.Errorf("Create table with specified table")
  144. }
  145. DB.Table("deleted_users").Save(&User{Name: "DeletedUser"})
  146. var deletedUsers []User
  147. DB.Table("deleted_users").Find(&deletedUsers)
  148. if len(deletedUsers) != 1 {
  149. t.Errorf("Query from specified table")
  150. }
  151. DB.Save(getPreparedUser("normal_user", "reset_table"))
  152. DB.Table("deleted_users").Save(getPreparedUser("deleted_user", "reset_table"))
  153. var user1, user2, user3 User
  154. DB.Where("role = ?", "reset_table").First(&user1).Table("deleted_users").First(&user2).Table("").First(&user3)
  155. if (user1.Name != "normal_user") || (user2.Name != "deleted_user") || (user3.Name != "normal_user") {
  156. t.Errorf("unset specified table with blank string")
  157. }
  158. }
  159. type Order struct {
  160. }
  161. type Cart struct {
  162. }
  163. func (c Cart) TableName() string {
  164. return "shopping_cart"
  165. }
  166. func TestHasTable(t *testing.T) {
  167. type Foo struct {
  168. Id int
  169. Stuff string
  170. }
  171. DB.DropTable(&Foo{})
  172. // Table should not exist at this point, HasTable should return false
  173. if ok := DB.HasTable("foos"); ok {
  174. t.Errorf("Table should not exist, but does")
  175. }
  176. if ok := DB.HasTable(&Foo{}); ok {
  177. t.Errorf("Table should not exist, but does")
  178. }
  179. // We create the table
  180. if err := DB.CreateTable(&Foo{}).Error; err != nil {
  181. t.Errorf("Table should be created")
  182. }
  183. // And now it should exits, and HasTable should return true
  184. if ok := DB.HasTable("foos"); !ok {
  185. t.Errorf("Table should exist, but HasTable informs it does not")
  186. }
  187. if ok := DB.HasTable(&Foo{}); !ok {
  188. t.Errorf("Table should exist, but HasTable informs it does not")
  189. }
  190. }
  191. func TestTableName(t *testing.T) {
  192. DB := DB.Model("")
  193. if DB.NewScope(Order{}).TableName() != "orders" {
  194. t.Errorf("Order's table name should be orders")
  195. }
  196. if DB.NewScope(&Order{}).TableName() != "orders" {
  197. t.Errorf("&Order's table name should be orders")
  198. }
  199. if DB.NewScope([]Order{}).TableName() != "orders" {
  200. t.Errorf("[]Order's table name should be orders")
  201. }
  202. if DB.NewScope(&[]Order{}).TableName() != "orders" {
  203. t.Errorf("&[]Order's table name should be orders")
  204. }
  205. DB.SingularTable(true)
  206. if DB.NewScope(Order{}).TableName() != "order" {
  207. t.Errorf("Order's singular table name should be order")
  208. }
  209. if DB.NewScope(&Order{}).TableName() != "order" {
  210. t.Errorf("&Order's singular table name should be order")
  211. }
  212. if DB.NewScope([]Order{}).TableName() != "order" {
  213. t.Errorf("[]Order's singular table name should be order")
  214. }
  215. if DB.NewScope(&[]Order{}).TableName() != "order" {
  216. t.Errorf("&[]Order's singular table name should be order")
  217. }
  218. if DB.NewScope(&Cart{}).TableName() != "shopping_cart" {
  219. t.Errorf("&Cart's singular table name should be shopping_cart")
  220. }
  221. if DB.NewScope(Cart{}).TableName() != "shopping_cart" {
  222. t.Errorf("Cart's singular table name should be shopping_cart")
  223. }
  224. if DB.NewScope(&[]Cart{}).TableName() != "shopping_cart" {
  225. t.Errorf("&[]Cart's singular table name should be shopping_cart")
  226. }
  227. if DB.NewScope([]Cart{}).TableName() != "shopping_cart" {
  228. t.Errorf("[]Cart's singular table name should be shopping_cart")
  229. }
  230. DB.SingularTable(false)
  231. }
  232. func TestNullValues(t *testing.T) {
  233. DB.DropTable(&NullValue{})
  234. DB.AutoMigrate(&NullValue{})
  235. if err := DB.Save(&NullValue{
  236. Name: sql.NullString{String: "hello", Valid: true},
  237. Gender: &sql.NullString{String: "M", Valid: true},
  238. Age: sql.NullInt64{Int64: 18, Valid: true},
  239. Male: sql.NullBool{Bool: true, Valid: true},
  240. Height: sql.NullFloat64{Float64: 100.11, Valid: true},
  241. AddedAt: NullTime{Time: time.Now(), Valid: true},
  242. }).Error; err != nil {
  243. t.Errorf("Not error should raise when test null value")
  244. }
  245. var nv NullValue
  246. DB.First(&nv, "name = ?", "hello")
  247. if nv.Name.String != "hello" || nv.Gender.String != "M" || nv.Age.Int64 != 18 || nv.Male.Bool != true || nv.Height.Float64 != 100.11 || nv.AddedAt.Valid != true {
  248. t.Errorf("Should be able to fetch null value")
  249. }
  250. if err := DB.Save(&NullValue{
  251. Name: sql.NullString{String: "hello-2", Valid: true},
  252. Gender: &sql.NullString{String: "F", Valid: true},
  253. Age: sql.NullInt64{Int64: 18, Valid: false},
  254. Male: sql.NullBool{Bool: true, Valid: true},
  255. Height: sql.NullFloat64{Float64: 100.11, Valid: true},
  256. AddedAt: NullTime{Time: time.Now(), Valid: false},
  257. }).Error; err != nil {
  258. t.Errorf("Not error should raise when test null value")
  259. }
  260. var nv2 NullValue
  261. DB.First(&nv2, "name = ?", "hello-2")
  262. if nv2.Name.String != "hello-2" || nv2.Gender.String != "F" || nv2.Age.Int64 != 0 || nv2.Male.Bool != true || nv2.Height.Float64 != 100.11 || nv2.AddedAt.Valid != false {
  263. t.Errorf("Should be able to fetch null value")
  264. }
  265. if err := DB.Save(&NullValue{
  266. Name: sql.NullString{String: "hello-3", Valid: false},
  267. Gender: &sql.NullString{String: "M", Valid: true},
  268. Age: sql.NullInt64{Int64: 18, Valid: false},
  269. Male: sql.NullBool{Bool: true, Valid: true},
  270. Height: sql.NullFloat64{Float64: 100.11, Valid: true},
  271. AddedAt: NullTime{Time: time.Now(), Valid: false},
  272. }).Error; err == nil {
  273. t.Errorf("Can't save because of name can't be null")
  274. }
  275. }
  276. func TestNullValuesWithFirstOrCreate(t *testing.T) {
  277. var nv1 = NullValue{
  278. Name: sql.NullString{String: "first_or_create", Valid: true},
  279. Gender: &sql.NullString{String: "M", Valid: true},
  280. }
  281. var nv2 NullValue
  282. result := DB.Where(nv1).FirstOrCreate(&nv2)
  283. if result.RowsAffected != 1 {
  284. t.Errorf("RowsAffected should be 1 after create some record")
  285. }
  286. if result.Error != nil {
  287. t.Errorf("Should not raise any error, but got %v", result.Error)
  288. }
  289. if nv2.Name.String != "first_or_create" || nv2.Gender.String != "M" {
  290. t.Errorf("first or create with nullvalues")
  291. }
  292. if err := DB.Where(nv1).Assign(NullValue{Age: sql.NullInt64{Int64: 18, Valid: true}}).FirstOrCreate(&nv2).Error; err != nil {
  293. t.Errorf("Should not raise any error, but got %v", err)
  294. }
  295. if nv2.Age.Int64 != 18 {
  296. t.Errorf("should update age to 18")
  297. }
  298. }
  299. func TestTransaction(t *testing.T) {
  300. tx := DB.Begin()
  301. u := User{Name: "transcation"}
  302. if err := tx.Save(&u).Error; err != nil {
  303. t.Errorf("No error should raise")
  304. }
  305. if err := tx.First(&User{}, "name = ?", "transcation").Error; err != nil {
  306. t.Errorf("Should find saved record")
  307. }
  308. if sqlTx, ok := tx.CommonDB().(*sql.Tx); !ok || sqlTx == nil {
  309. t.Errorf("Should return the underlying sql.Tx")
  310. }
  311. tx.Rollback()
  312. if err := tx.First(&User{}, "name = ?", "transcation").Error; err == nil {
  313. t.Errorf("Should not find record after rollback")
  314. }
  315. tx2 := DB.Begin()
  316. u2 := User{Name: "transcation-2"}
  317. if err := tx2.Save(&u2).Error; err != nil {
  318. t.Errorf("No error should raise")
  319. }
  320. if err := tx2.First(&User{}, "name = ?", "transcation-2").Error; err != nil {
  321. t.Errorf("Should find saved record")
  322. }
  323. tx2.Commit()
  324. if err := DB.First(&User{}, "name = ?", "transcation-2").Error; err != nil {
  325. t.Errorf("Should be able to find committed record")
  326. }
  327. }
  328. func TestRow(t *testing.T) {
  329. user1 := User{Name: "RowUser1", Age: 1, Birthday: parseTime("2000-1-1")}
  330. user2 := User{Name: "RowUser2", Age: 10, Birthday: parseTime("2010-1-1")}
  331. user3 := User{Name: "RowUser3", Age: 20, Birthday: parseTime("2020-1-1")}
  332. DB.Save(&user1).Save(&user2).Save(&user3)
  333. row := DB.Table("users").Where("name = ?", user2.Name).Select("age").Row()
  334. var age int64
  335. row.Scan(&age)
  336. if age != 10 {
  337. t.Errorf("Scan with Row")
  338. }
  339. }
  340. func TestRows(t *testing.T) {
  341. user1 := User{Name: "RowsUser1", Age: 1, Birthday: parseTime("2000-1-1")}
  342. user2 := User{Name: "RowsUser2", Age: 10, Birthday: parseTime("2010-1-1")}
  343. user3 := User{Name: "RowsUser3", Age: 20, Birthday: parseTime("2020-1-1")}
  344. DB.Save(&user1).Save(&user2).Save(&user3)
  345. rows, err := DB.Table("users").Where("name = ? or name = ?", user2.Name, user3.Name).Select("name, age").Rows()
  346. if err != nil {
  347. t.Errorf("Not error should happen, got %v", err)
  348. }
  349. count := 0
  350. for rows.Next() {
  351. var name string
  352. var age int64
  353. rows.Scan(&name, &age)
  354. count++
  355. }
  356. if count != 2 {
  357. t.Errorf("Should found two records")
  358. }
  359. }
  360. func TestScanRows(t *testing.T) {
  361. user1 := User{Name: "ScanRowsUser1", Age: 1, Birthday: parseTime("2000-1-1")}
  362. user2 := User{Name: "ScanRowsUser2", Age: 10, Birthday: parseTime("2010-1-1")}
  363. user3 := User{Name: "ScanRowsUser3", Age: 20, Birthday: parseTime("2020-1-1")}
  364. DB.Save(&user1).Save(&user2).Save(&user3)
  365. rows, err := DB.Table("users").Where("name = ? or name = ?", user2.Name, user3.Name).Select("name, age").Rows()
  366. if err != nil {
  367. t.Errorf("Not error should happen, got %v", err)
  368. }
  369. type Result struct {
  370. Name string
  371. Age int
  372. }
  373. var results []Result
  374. for rows.Next() {
  375. var result Result
  376. if err := DB.ScanRows(rows, &result); err != nil {
  377. t.Errorf("should get no error, but got %v", err)
  378. }
  379. results = append(results, result)
  380. }
  381. if !reflect.DeepEqual(results, []Result{{Name: "ScanRowsUser2", Age: 10}, {Name: "ScanRowsUser3", Age: 20}}) {
  382. t.Errorf("Should find expected results")
  383. }
  384. }
  385. func TestScan(t *testing.T) {
  386. user1 := User{Name: "ScanUser1", Age: 1, Birthday: parseTime("2000-1-1")}
  387. user2 := User{Name: "ScanUser2", Age: 10, Birthday: parseTime("2010-1-1")}
  388. user3 := User{Name: "ScanUser3", Age: 20, Birthday: parseTime("2020-1-1")}
  389. DB.Save(&user1).Save(&user2).Save(&user3)
  390. type result struct {
  391. Name string
  392. Age int
  393. }
  394. var res result
  395. DB.Table("users").Select("name, age").Where("name = ?", user3.Name).Scan(&res)
  396. if res.Name != user3.Name {
  397. t.Errorf("Scan into struct should work")
  398. }
  399. var doubleAgeRes = &result{}
  400. if err := DB.Table("users").Select("age + age as age").Where("name = ?", user3.Name).Scan(&doubleAgeRes).Error; err != nil {
  401. t.Errorf("Scan to pointer of pointer")
  402. }
  403. if doubleAgeRes.Age != res.Age*2 {
  404. t.Errorf("Scan double age as age")
  405. }
  406. var ress []result
  407. DB.Table("users").Select("name, age").Where("name in (?)", []string{user2.Name, user3.Name}).Scan(&ress)
  408. if len(ress) != 2 || ress[0].Name != user2.Name || ress[1].Name != user3.Name {
  409. t.Errorf("Scan into struct map")
  410. }
  411. }
  412. func TestRaw(t *testing.T) {
  413. user1 := User{Name: "ExecRawSqlUser1", Age: 1, Birthday: parseTime("2000-1-1")}
  414. user2 := User{Name: "ExecRawSqlUser2", Age: 10, Birthday: parseTime("2010-1-1")}
  415. user3 := User{Name: "ExecRawSqlUser3", Age: 20, Birthday: parseTime("2020-1-1")}
  416. DB.Save(&user1).Save(&user2).Save(&user3)
  417. type result struct {
  418. Name string
  419. Email string
  420. }
  421. var ress []result
  422. DB.Raw("SELECT name, age FROM users WHERE name = ? or name = ?", user2.Name, user3.Name).Scan(&ress)
  423. if len(ress) != 2 || ress[0].Name != user2.Name || ress[1].Name != user3.Name {
  424. t.Errorf("Raw with scan")
  425. }
  426. rows, _ := DB.Raw("select name, age from users where name = ?", user3.Name).Rows()
  427. count := 0
  428. for rows.Next() {
  429. count++
  430. }
  431. if count != 1 {
  432. t.Errorf("Raw with Rows should find one record with name 3")
  433. }
  434. DB.Exec("update users set name=? where name in (?)", "jinzhu", []string{user1.Name, user2.Name, user3.Name})
  435. if DB.Where("name in (?)", []string{user1.Name, user2.Name, user3.Name}).First(&User{}).Error != gorm.ErrRecordNotFound {
  436. t.Error("Raw sql to update records")
  437. }
  438. }
  439. func TestGroup(t *testing.T) {
  440. rows, err := DB.Select("name").Table("users").Group("name").Rows()
  441. if err == nil {
  442. defer rows.Close()
  443. for rows.Next() {
  444. var name string
  445. rows.Scan(&name)
  446. }
  447. } else {
  448. t.Errorf("Should not raise any error")
  449. }
  450. }
  451. func TestJoins(t *testing.T) {
  452. var user = User{
  453. Name: "joins",
  454. CreditCard: CreditCard{Number: "411111111111"},
  455. Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}},
  456. }
  457. DB.Save(&user)
  458. var users1 []User
  459. DB.Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins").Find(&users1)
  460. if len(users1) != 2 {
  461. t.Errorf("should find two users using left join")
  462. }
  463. var users2 []User
  464. DB.Joins("left join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Where("name = ?", "joins").First(&users2)
  465. if len(users2) != 1 {
  466. t.Errorf("should find one users using left join with conditions")
  467. }
  468. var users3 []User
  469. DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "411111111111").Where("name = ?", "joins").First(&users3)
  470. if len(users3) != 1 {
  471. t.Errorf("should find one users using multiple left join conditions")
  472. }
  473. var users4 []User
  474. DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "422222222222").Where("name = ?", "joins").First(&users4)
  475. if len(users4) != 0 {
  476. t.Errorf("should find no user when searching with unexisting credit card")
  477. }
  478. var users5 []User
  479. db5 := DB.Joins("join emails on emails.user_id = users.id AND emails.email = ?", "join1@example.com").Joins("join credit_cards on credit_cards.user_id = users.id AND credit_cards.number = ?", "411111111111").Where(User{Id: 1}).Where(Email{Id: 1}).Not(Email{Id: 10}).First(&users5)
  480. if db5.Error != nil {
  481. t.Errorf("Should not raise error for join where identical fields in different tables. Error: %s", db5.Error.Error())
  482. }
  483. }
  484. type JoinedIds struct {
  485. UserID int64 `gorm:"column:id"`
  486. BillingAddressID int64 `gorm:"column:id"`
  487. EmailID int64 `gorm:"column:id"`
  488. }
  489. func TestScanIdenticalColumnNames(t *testing.T) {
  490. var user = User{
  491. Name: "joinsIds",
  492. Email: "joinIds@example.com",
  493. BillingAddress: Address{
  494. Address1: "One Park Place",
  495. },
  496. Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}},
  497. }
  498. DB.Save(&user)
  499. var users []JoinedIds
  500. DB.Select("users.id, addresses.id, emails.id").Table("users").
  501. Joins("left join addresses on users.billing_address_id = addresses.id").
  502. Joins("left join emails on emails.user_id = users.id").
  503. Where("name = ?", "joinsIds").Scan(&users)
  504. if len(users) != 2 {
  505. t.Fatal("should find two rows using left join")
  506. }
  507. if user.Id != users[0].UserID {
  508. t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[0].UserID)
  509. }
  510. if user.Id != users[1].UserID {
  511. t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[1].UserID)
  512. }
  513. if user.BillingAddressID.Int64 != users[0].BillingAddressID {
  514. t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID)
  515. }
  516. if user.BillingAddressID.Int64 != users[1].BillingAddressID {
  517. t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID)
  518. }
  519. if users[0].EmailID == users[1].EmailID {
  520. t.Errorf("Email ids should be unique. Got %d and %d", users[0].EmailID, users[1].EmailID)
  521. }
  522. if int64(user.Emails[0].Id) != users[0].EmailID && int64(user.Emails[1].Id) != users[0].EmailID {
  523. t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[0].EmailID)
  524. }
  525. if int64(user.Emails[0].Id) != users[1].EmailID && int64(user.Emails[1].Id) != users[1].EmailID {
  526. t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[1].EmailID)
  527. }
  528. }
  529. func TestJoinsWithSelect(t *testing.T) {
  530. type result struct {
  531. Name string
  532. Email string
  533. }
  534. user := User{
  535. Name: "joins_with_select",
  536. Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}},
  537. }
  538. DB.Save(&user)
  539. var results []result
  540. DB.Table("users").Select("name, emails.email").Joins("left join emails on emails.user_id = users.id").Where("name = ?", "joins_with_select").Scan(&results)
  541. if len(results) != 2 || results[0].Email != "join1@example.com" || results[1].Email != "join2@example.com" {
  542. t.Errorf("Should find all two emails with Join select")
  543. }
  544. }
  545. func TestHaving(t *testing.T) {
  546. rows, err := DB.Select("name, count(*) as total").Table("users").Group("name").Having("name IN (?)", []string{"2", "3"}).Rows()
  547. if err == nil {
  548. defer rows.Close()
  549. for rows.Next() {
  550. var name string
  551. var total int64
  552. rows.Scan(&name, &total)
  553. if name == "2" && total != 1 {
  554. t.Errorf("Should have one user having name 2")
  555. }
  556. if name == "3" && total != 2 {
  557. t.Errorf("Should have two users having name 3")
  558. }
  559. }
  560. } else {
  561. t.Errorf("Should not raise any error")
  562. }
  563. }
  564. func TestQueryBuilderSubselectInWhere(t *testing.T) {
  565. user := User{Name: "query_expr_select_ruser1", Email: "root@user1.com", Age: 32}
  566. DB.Save(&user)
  567. user = User{Name: "query_expr_select_ruser2", Email: "nobody@user2.com", Age: 16}
  568. DB.Save(&user)
  569. user = User{Name: "query_expr_select_ruser3", Email: "root@user3.com", Age: 64}
  570. DB.Save(&user)
  571. user = User{Name: "query_expr_select_ruser4", Email: "somebody@user3.com", Age: 128}
  572. DB.Save(&user)
  573. var users []User
  574. DB.Select("*").Where("name IN (?)", DB.
  575. Select("name").Table("users").Where("name LIKE ?", "query_expr_select%").QueryExpr()).Find(&users)
  576. if len(users) != 4 {
  577. t.Errorf("Four users should be found, instead found %d", len(users))
  578. }
  579. DB.Select("*").Where("name LIKE ?", "query_expr_select%").Where("age >= (?)", DB.
  580. Select("AVG(age)").Table("users").Where("name LIKE ?", "query_expr_select%").QueryExpr()).Find(&users)
  581. if len(users) != 2 {
  582. t.Errorf("Two users should be found, instead found %d", len(users))
  583. }
  584. }
  585. func TestQueryBuilderRawQueryWithSubquery(t *testing.T) {
  586. user := User{Name: "subquery_test_user1", Age: 10}
  587. DB.Save(&user)
  588. user = User{Name: "subquery_test_user2", Age: 11}
  589. DB.Save(&user)
  590. user = User{Name: "subquery_test_user3", Age: 12}
  591. DB.Save(&user)
  592. var count int
  593. err := DB.Raw("select count(*) from (?) tmp",
  594. DB.Table("users").
  595. Select("name").
  596. Where("age >= ? and name in (?)", 10, []string{"subquery_test_user1", "subquery_test_user2"}).
  597. Group("name").
  598. QueryExpr(),
  599. ).Count(&count).Error
  600. if err != nil {
  601. t.Errorf("Expected to get no errors, but got %v", err)
  602. }
  603. if count != 2 {
  604. t.Errorf("Row count must be 2, instead got %d", count)
  605. }
  606. err = DB.Raw("select count(*) from (?) tmp",
  607. DB.Table("users").
  608. Select("name").
  609. Where("name LIKE ?", "subquery_test%").
  610. Not("age <= ?", 10).Not("name in (?)", []string{"subquery_test_user1", "subquery_test_user2"}).
  611. Group("name").
  612. QueryExpr(),
  613. ).Count(&count).Error
  614. if err != nil {
  615. t.Errorf("Expected to get no errors, but got %v", err)
  616. }
  617. if count != 1 {
  618. t.Errorf("Row count must be 1, instead got %d", count)
  619. }
  620. }
  621. func TestQueryBuilderSubselectInHaving(t *testing.T) {
  622. user := User{Name: "query_expr_having_ruser1", Email: "root@user1.com", Age: 64}
  623. DB.Save(&user)
  624. user = User{Name: "query_expr_having_ruser2", Email: "root@user2.com", Age: 128}
  625. DB.Save(&user)
  626. user = User{Name: "query_expr_having_ruser3", Email: "root@user1.com", Age: 64}
  627. DB.Save(&user)
  628. user = User{Name: "query_expr_having_ruser4", Email: "root@user2.com", Age: 128}
  629. DB.Save(&user)
  630. var users []User
  631. DB.Select("AVG(age) as avgage").Where("name LIKE ?", "query_expr_having_%").Group("email").Having("AVG(age) > (?)", DB.
  632. Select("AVG(age)").Where("name LIKE ?", "query_expr_having_%").Table("users").QueryExpr()).Find(&users)
  633. if len(users) != 1 {
  634. t.Errorf("Two user group should be found, instead found %d", len(users))
  635. }
  636. }
  637. func DialectHasTzSupport() bool {
  638. // NB: mssql and FoundationDB do not support time zones.
  639. if dialect := os.Getenv("GORM_DIALECT"); dialect == "foundation" {
  640. return false
  641. }
  642. return true
  643. }
  644. func TestTimeWithZone(t *testing.T) {
  645. var format = "2006-01-02 15:04:05 -0700"
  646. var times []time.Time
  647. GMT8, _ := time.LoadLocation("Asia/Shanghai")
  648. times = append(times, time.Date(2013, 02, 19, 1, 51, 49, 123456789, GMT8))
  649. times = append(times, time.Date(2013, 02, 18, 17, 51, 49, 123456789, time.UTC))
  650. for index, vtime := range times {
  651. name := "time_with_zone_" + strconv.Itoa(index)
  652. user := User{Name: name, Birthday: &vtime}
  653. if !DialectHasTzSupport() {
  654. // If our driver dialect doesn't support TZ's, just use UTC for everything here.
  655. utcBirthday := user.Birthday.UTC()
  656. user.Birthday = &utcBirthday
  657. }
  658. DB.Save(&user)
  659. expectedBirthday := "2013-02-18 17:51:49 +0000"
  660. foundBirthday := user.Birthday.UTC().Format(format)
  661. if foundBirthday != expectedBirthday {
  662. t.Errorf("User's birthday should not be changed after save for name=%s, expected bday=%+v but actual value=%+v", name, expectedBirthday, foundBirthday)
  663. }
  664. var findUser, findUser2, findUser3 User
  665. DB.First(&findUser, "name = ?", name)
  666. foundBirthday = findUser.Birthday.UTC().Format(format)
  667. if foundBirthday != expectedBirthday {
  668. t.Errorf("User's birthday should not be changed after find for name=%s, expected bday=%+v but actual value=%+v", name, expectedBirthday, foundBirthday)
  669. }
  670. if DB.Where("id = ? AND birthday >= ?", findUser.Id, user.Birthday.Add(-time.Minute)).First(&findUser2).RecordNotFound() {
  671. t.Errorf("User should be found")
  672. }
  673. if !DB.Where("id = ? AND birthday >= ?", findUser.Id, user.Birthday.Add(time.Minute)).First(&findUser3).RecordNotFound() {
  674. t.Errorf("User should not be found")
  675. }
  676. }
  677. }
  678. func TestHstore(t *testing.T) {
  679. type Details struct {
  680. Id int64
  681. Bulk postgres.Hstore
  682. }
  683. if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" {
  684. t.Skip()
  685. }
  686. if err := DB.Exec("CREATE EXTENSION IF NOT EXISTS hstore").Error; err != nil {
  687. fmt.Println("\033[31mHINT: Must be superuser to create hstore extension (ALTER USER gorm WITH SUPERUSER;)\033[0m")
  688. panic(fmt.Sprintf("No error should happen when create hstore extension, but got %+v", err))
  689. }
  690. DB.Exec("drop table details")
  691. if err := DB.CreateTable(&Details{}).Error; err != nil {
  692. panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
  693. }
  694. bankAccountId, phoneNumber, opinion := "123456", "14151321232", "sharkbait"
  695. bulk := map[string]*string{
  696. "bankAccountId": &bankAccountId,
  697. "phoneNumber": &phoneNumber,
  698. "opinion": &opinion,
  699. }
  700. d := Details{Bulk: bulk}
  701. DB.Save(&d)
  702. var d2 Details
  703. if err := DB.First(&d2).Error; err != nil {
  704. t.Errorf("Got error when tried to fetch details: %+v", err)
  705. }
  706. for k := range bulk {
  707. if r, ok := d2.Bulk[k]; ok {
  708. if res, _ := bulk[k]; *res != *r {
  709. t.Errorf("Details should be equal")
  710. }
  711. } else {
  712. t.Errorf("Details should be existed")
  713. }
  714. }
  715. }
  716. func TestSetAndGet(t *testing.T) {
  717. if value, ok := DB.Set("hello", "world").Get("hello"); !ok {
  718. t.Errorf("Should be able to get setting after set")
  719. } else {
  720. if value.(string) != "world" {
  721. t.Errorf("Setted value should not be changed")
  722. }
  723. }
  724. if _, ok := DB.Get("non_existing"); ok {
  725. t.Errorf("Get non existing key should return error")
  726. }
  727. }
  728. func TestCompatibilityMode(t *testing.T) {
  729. DB, _ := gorm.Open("testdb", "")
  730. testdb.SetQueryFunc(func(query string) (driver.Rows, error) {
  731. columns := []string{"id", "name", "age"}
  732. result := `
  733. 1,Tim,20
  734. 2,Joe,25
  735. 3,Bob,30
  736. `
  737. return testdb.RowsFromCSVString(columns, result), nil
  738. })
  739. var users []User
  740. DB.Find(&users)
  741. if (users[0].Name != "Tim") || len(users) != 3 {
  742. t.Errorf("Unexcepted result returned")
  743. }
  744. }
  745. func TestOpenExistingDB(t *testing.T) {
  746. DB.Save(&User{Name: "jnfeinstein"})
  747. dialect := os.Getenv("GORM_DIALECT")
  748. db, err := gorm.Open(dialect, DB.DB())
  749. if err != nil {
  750. t.Errorf("Should have wrapped the existing DB connection")
  751. }
  752. var user User
  753. if db.Where("name = ?", "jnfeinstein").First(&user).Error == gorm.ErrRecordNotFound {
  754. t.Errorf("Should have found existing record")
  755. }
  756. }
  757. func TestDdlErrors(t *testing.T) {
  758. var err error
  759. if err = DB.Close(); err != nil {
  760. t.Errorf("Closing DDL test db connection err=%s", err)
  761. }
  762. defer func() {
  763. // Reopen DB connection.
  764. if DB, err = OpenTestConnection(); err != nil {
  765. t.Fatalf("Failed re-opening db connection: %s", err)
  766. }
  767. }()
  768. if err := DB.Find(&User{}).Error; err == nil {
  769. t.Errorf("Expected operation on closed db to produce an error, but err was nil")
  770. }
  771. }
  772. func TestOpenWithOneParameter(t *testing.T) {
  773. db, err := gorm.Open("dialect")
  774. if db != nil {
  775. t.Error("Open with one parameter returned non nil for db")
  776. }
  777. if err == nil {
  778. t.Error("Open with one parameter returned err as nil")
  779. }
  780. }
  781. func TestSaveAssociations(t *testing.T) {
  782. db := DB.New()
  783. deltaAddressCount := 0
  784. if err := db.Model(&Address{}).Count(&deltaAddressCount).Error; err != nil {
  785. t.Errorf("failed to fetch address count")
  786. t.FailNow()
  787. }
  788. placeAddress := &Address{
  789. Address1: "somewhere on earth",
  790. }
  791. ownerAddress1 := &Address{
  792. Address1: "near place address",
  793. }
  794. ownerAddress2 := &Address{
  795. Address1: "address2",
  796. }
  797. db.Create(placeAddress)
  798. addressCountShouldBe := func(t *testing.T, expectedCount int) {
  799. countFromDB := 0
  800. t.Helper()
  801. err := db.Model(&Address{}).Count(&countFromDB).Error
  802. if err != nil {
  803. t.Error("failed to fetch address count")
  804. }
  805. if countFromDB != expectedCount {
  806. t.Errorf("address count mismatch: %d", countFromDB)
  807. }
  808. }
  809. addressCountShouldBe(t, deltaAddressCount+1)
  810. // owner address should be created, place address should be reused
  811. place1 := &Place{
  812. PlaceAddressID: placeAddress.ID,
  813. PlaceAddress: placeAddress,
  814. OwnerAddress: ownerAddress1,
  815. }
  816. err := db.Create(place1).Error
  817. if err != nil {
  818. t.Errorf("failed to store place: %s", err.Error())
  819. }
  820. addressCountShouldBe(t, deltaAddressCount+2)
  821. // owner address should be created again, place address should be reused
  822. place2 := &Place{
  823. PlaceAddressID: placeAddress.ID,
  824. PlaceAddress: &Address{
  825. ID: 777,
  826. Address1: "address1",
  827. },
  828. OwnerAddress: ownerAddress2,
  829. OwnerAddressID: 778,
  830. }
  831. err = db.Create(place2).Error
  832. if err != nil {
  833. t.Errorf("failed to store place: %s", err.Error())
  834. }
  835. addressCountShouldBe(t, deltaAddressCount+3)
  836. count := 0
  837. db.Model(&Place{}).Where(&Place{
  838. PlaceAddressID: placeAddress.ID,
  839. OwnerAddressID: ownerAddress1.ID,
  840. }).Count(&count)
  841. if count != 1 {
  842. t.Errorf("only one instance of (%d, %d) should be available, found: %d",
  843. placeAddress.ID, ownerAddress1.ID, count)
  844. }
  845. db.Model(&Place{}).Where(&Place{
  846. PlaceAddressID: placeAddress.ID,
  847. OwnerAddressID: ownerAddress2.ID,
  848. }).Count(&count)
  849. if count != 1 {
  850. t.Errorf("only one instance of (%d, %d) should be available, found: %d",
  851. placeAddress.ID, ownerAddress2.ID, count)
  852. }
  853. db.Model(&Place{}).Where(&Place{
  854. PlaceAddressID: placeAddress.ID,
  855. }).Count(&count)
  856. if count != 2 {
  857. t.Errorf("two instances of (%d) should be available, found: %d",
  858. placeAddress.ID, count)
  859. }
  860. }
  861. func TestBlockGlobalUpdate(t *testing.T) {
  862. db := DB.New()
  863. db.Create(&Toy{Name: "Stuffed Animal", OwnerType: "Nobody"})
  864. err := db.Model(&Toy{}).Update("OwnerType", "Human").Error
  865. if err != nil {
  866. t.Error("Unexpected error on global update")
  867. }
  868. err = db.Delete(&Toy{}).Error
  869. if err != nil {
  870. t.Error("Unexpected error on global delete")
  871. }
  872. db.BlockGlobalUpdate(true)
  873. db.Create(&Toy{Name: "Stuffed Animal", OwnerType: "Nobody"})
  874. err = db.Model(&Toy{}).Update("OwnerType", "Human").Error
  875. if err == nil {
  876. t.Error("Expected error on global update")
  877. }
  878. err = db.Model(&Toy{}).Where(&Toy{OwnerType: "Martian"}).Update("OwnerType", "Astronaut").Error
  879. if err != nil {
  880. t.Error("Unxpected error on conditional update")
  881. }
  882. err = db.Delete(&Toy{}).Error
  883. if err == nil {
  884. t.Error("Expected error on global delete")
  885. }
  886. err = db.Where(&Toy{OwnerType: "Martian"}).Delete(&Toy{}).Error
  887. if err != nil {
  888. t.Error("Unexpected error on conditional delete")
  889. }
  890. }
  891. func BenchmarkGorm(b *testing.B) {
  892. b.N = 2000
  893. for x := 0; x < b.N; x++ {
  894. e := strconv.Itoa(x) + "benchmark@example.org"
  895. now := time.Now()
  896. email := EmailWithIdx{Email: e, UserAgent: "pc", RegisteredAt: &now}
  897. // Insert
  898. DB.Save(&email)
  899. // Query
  900. DB.First(&EmailWithIdx{}, "email = ?", e)
  901. // Update
  902. DB.Model(&email).UpdateColumn("email", "new-"+e)
  903. // Delete
  904. DB.Delete(&email)
  905. }
  906. }
  907. func BenchmarkRawSql(b *testing.B) {
  908. DB, _ := sql.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable")
  909. DB.SetMaxIdleConns(10)
  910. insertSql := "INSERT INTO emails (user_id,email,user_agent,registered_at,created_at,updated_at) VALUES ($1,$2,$3,$4,$5,$6) RETURNING id"
  911. querySql := "SELECT * FROM emails WHERE email = $1 ORDER BY id LIMIT 1"
  912. updateSql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
  913. deleteSql := "DELETE FROM orders WHERE id = $1"
  914. b.N = 2000
  915. for x := 0; x < b.N; x++ {
  916. var id int64
  917. e := strconv.Itoa(x) + "benchmark@example.org"
  918. now := time.Now()
  919. email := EmailWithIdx{Email: e, UserAgent: "pc", RegisteredAt: &now}
  920. // Insert
  921. DB.QueryRow(insertSql, email.UserId, email.Email, email.UserAgent, email.RegisteredAt, time.Now(), time.Now()).Scan(&id)
  922. // Query
  923. rows, _ := DB.Query(querySql, email.Email)
  924. rows.Close()
  925. // Update
  926. DB.Exec(updateSql, "new-"+e, time.Now(), id)
  927. // Delete
  928. DB.Exec(deleteSql, id)
  929. }
  930. }
  931. func parseTime(str string) *time.Time {
  932. t := now.New(time.Now().UTC()).MustParse(str)
  933. return &t
  934. }