main_test.go 38 KB

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