main_test.go 41 KB

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