statement_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // Copyright 2017 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package xorm
  5. import (
  6. "reflect"
  7. "strings"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/xormplus/core"
  11. )
  12. var colStrTests = []struct {
  13. omitColumn string
  14. onlyToDBColumnNdx int
  15. expected string
  16. }{
  17. {"", -1, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`, `Longitude`"},
  18. {"Code2", -1, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code3`, `ParentID`, `Latitude`, `Longitude`"},
  19. {"", 1, "`ID`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`, `Longitude`"},
  20. {"Code3", 1, "`ID`, `Caption`, `Code1`, `Code2`, `ParentID`, `Latitude`, `Longitude`"},
  21. {"Longitude", 1, "`ID`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`"},
  22. {"", 8, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`"},
  23. }
  24. func TestColumnsStringGeneration(t *testing.T) {
  25. if dbType == "postgres" || dbType == "mssql" {
  26. return
  27. }
  28. var statement *Statement
  29. for ndx, testCase := range colStrTests {
  30. statement = createTestStatement()
  31. if testCase.omitColumn != "" {
  32. statement.Omit(testCase.omitColumn)
  33. }
  34. columns := statement.RefTable.Columns()
  35. if testCase.onlyToDBColumnNdx >= 0 {
  36. columns[testCase.onlyToDBColumnNdx].MapType = core.ONLYTODB
  37. }
  38. actual := statement.genColumnStr()
  39. if actual != testCase.expected {
  40. t.Errorf("[test #%d] Unexpected columns string:\nwant:\t%s\nhave:\t%s", ndx, testCase.expected, actual)
  41. }
  42. if testCase.onlyToDBColumnNdx >= 0 {
  43. columns[testCase.onlyToDBColumnNdx].MapType = core.TWOSIDES
  44. }
  45. }
  46. }
  47. func BenchmarkColumnsStringGeneration(b *testing.B) {
  48. b.StopTimer()
  49. statement := createTestStatement()
  50. testCase := colStrTests[0]
  51. if testCase.omitColumn != "" {
  52. statement.Omit(testCase.omitColumn) // !nemec784! Column must be skipped
  53. }
  54. if testCase.onlyToDBColumnNdx >= 0 {
  55. columns := statement.RefTable.Columns()
  56. columns[testCase.onlyToDBColumnNdx].MapType = core.ONLYTODB // !nemec784! Column must be skipped
  57. }
  58. b.StartTimer()
  59. for i := 0; i < b.N; i++ {
  60. actual := statement.genColumnStr()
  61. if actual != testCase.expected {
  62. b.Errorf("Unexpected columns string:\nwant:\t%s\nhave:\t%s", testCase.expected, actual)
  63. }
  64. }
  65. }
  66. func BenchmarkGetFlagForColumnWithICKey_ContainsKey(b *testing.B) {
  67. b.StopTimer()
  68. mapCols := make(map[string]bool)
  69. cols := []*core.Column{
  70. {Name: `ID`},
  71. {Name: `IsDeleted`},
  72. {Name: `Caption`},
  73. {Name: `Code1`},
  74. {Name: `Code2`},
  75. {Name: `Code3`},
  76. {Name: `ParentID`},
  77. {Name: `Latitude`},
  78. {Name: `Longitude`},
  79. }
  80. for _, col := range cols {
  81. mapCols[strings.ToLower(col.Name)] = true
  82. }
  83. b.StartTimer()
  84. for i := 0; i < b.N; i++ {
  85. for _, col := range cols {
  86. if _, ok := getFlagForColumn(mapCols, col); !ok {
  87. b.Fatal("Unexpected result")
  88. }
  89. }
  90. }
  91. }
  92. func BenchmarkGetFlagForColumnWithICKey_EmptyMap(b *testing.B) {
  93. b.StopTimer()
  94. mapCols := make(map[string]bool)
  95. cols := []*core.Column{
  96. {Name: `ID`},
  97. {Name: `IsDeleted`},
  98. {Name: `Caption`},
  99. {Name: `Code1`},
  100. {Name: `Code2`},
  101. {Name: `Code3`},
  102. {Name: `ParentID`},
  103. {Name: `Latitude`},
  104. {Name: `Longitude`},
  105. }
  106. b.StartTimer()
  107. for i := 0; i < b.N; i++ {
  108. for _, col := range cols {
  109. if _, ok := getFlagForColumn(mapCols, col); ok {
  110. b.Fatal("Unexpected result")
  111. }
  112. }
  113. }
  114. }
  115. type TestType struct {
  116. ID int64 `xorm:"ID PK"`
  117. IsDeleted bool `xorm:"IsDeleted"`
  118. Caption string `xorm:"Caption"`
  119. Code1 string `xorm:"Code1"`
  120. Code2 string `xorm:"Code2"`
  121. Code3 string `xorm:"Code3"`
  122. ParentID int64 `xorm:"ParentID"`
  123. Latitude float64 `xorm:"Latitude"`
  124. Longitude float64 `xorm:"Longitude"`
  125. }
  126. func (TestType) TableName() string {
  127. return "TestTable"
  128. }
  129. func createTestStatement() *Statement {
  130. if engine, ok := testEngine.(*Engine); ok {
  131. statement := &Statement{}
  132. statement.Init()
  133. statement.Engine = engine
  134. statement.setRefValue(reflect.ValueOf(TestType{}))
  135. return statement
  136. } else if eg, ok := testEngine.(*EngineGroup); ok {
  137. statement := &Statement{}
  138. statement.Init()
  139. statement.Engine = eg.Engine
  140. statement.setRefValue(reflect.ValueOf(TestType{}))
  141. return statement
  142. }
  143. return nil
  144. }
  145. func TestDistinctAndCols(t *testing.T) {
  146. type DistinctAndCols struct {
  147. Id int64
  148. Name string
  149. }
  150. assert.NoError(t, prepareEngine())
  151. assertSync(t, new(DistinctAndCols))
  152. cnt, err := testEngine.Insert(&DistinctAndCols{
  153. Name: "test",
  154. })
  155. assert.NoError(t, err)
  156. assert.EqualValues(t, 1, cnt)
  157. var names []string
  158. err = testEngine.Table("distinct_and_cols").Cols("name").Distinct("name").Find(&names)
  159. assert.NoError(t, err)
  160. assert.EqualValues(t, 1, len(names))
  161. assert.EqualValues(t, "test", names[0])
  162. }
  163. func TestUpdateIgnoreOnlyFromDBFields(t *testing.T) {
  164. type TestOnlyFromDBField struct {
  165. Id int64 `xorm:"PK"`
  166. OnlyFromDBField string `xorm:"<-"`
  167. OnlyToDBField string `xorm:"->"`
  168. IngoreField string `xorm:"-"`
  169. }
  170. assertGetRecord := func() *TestOnlyFromDBField {
  171. var record TestOnlyFromDBField
  172. has, err := testEngine.Where("id = ?", 1).Get(&record)
  173. assert.NoError(t, err)
  174. assert.EqualValues(t, true, has)
  175. assert.EqualValues(t, "", record.OnlyFromDBField)
  176. return &record
  177. }
  178. assert.NoError(t, prepareEngine())
  179. assertSync(t, new(TestOnlyFromDBField))
  180. _, err := testEngine.Insert(&TestOnlyFromDBField{
  181. Id: 1,
  182. OnlyFromDBField: "a",
  183. OnlyToDBField: "b",
  184. IngoreField: "c",
  185. })
  186. assert.NoError(t, err)
  187. record := assertGetRecord()
  188. record.OnlyFromDBField = "test"
  189. testEngine.Update(record)
  190. assertGetRecord()
  191. }
  192. func TestCol2NewColsWithQuote(t *testing.T) {
  193. cols := []string{"f1", "f2", "t3.f3"}
  194. statement := createTestStatement()
  195. quotedCols := statement.col2NewColsWithQuote(cols...)
  196. assert.EqualValues(t, []string{statement.Engine.Quote("f1"), statement.Engine.Quote("f2"), statement.Engine.Quote("t3.f3")}, quotedCols)
  197. }