sql_engine_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. package sqleng
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/grafana/grafana/pkg/components/null"
  7. "github.com/grafana/grafana/pkg/components/simplejson"
  8. "github.com/grafana/grafana/pkg/models"
  9. "github.com/grafana/grafana/pkg/tsdb"
  10. . "github.com/smartystreets/goconvey/convey"
  11. )
  12. func TestSqlEngine(t *testing.T) {
  13. Convey("SqlEngine", t, func() {
  14. dt := time.Date(2018, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC)
  15. earlyDt := time.Date(1970, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC)
  16. Convey("Given a time range between 2018-04-12 00:00 and 2018-04-12 00:05", func() {
  17. from := time.Date(2018, 4, 12, 18, 0, 0, 0, time.UTC)
  18. to := from.Add(5 * time.Minute)
  19. timeRange := tsdb.NewFakeTimeRange("5m", "now", to)
  20. query := &tsdb.Query{DataSource: &models.DataSource{}, Model: simplejson.New()}
  21. Convey("interpolate $__interval", func() {
  22. sql, err := Interpolate(query, timeRange, "select $__interval ")
  23. So(err, ShouldBeNil)
  24. So(sql, ShouldEqual, "select 1m ")
  25. })
  26. Convey("interpolate $__interval in $__timeGroup", func() {
  27. sql, err := Interpolate(query, timeRange, "select $__timeGroupAlias(time,$__interval)")
  28. So(err, ShouldBeNil)
  29. So(sql, ShouldEqual, "select $__timeGroupAlias(time,1m)")
  30. })
  31. Convey("interpolate $__interval_ms", func() {
  32. sql, err := Interpolate(query, timeRange, "select $__interval_ms ")
  33. So(err, ShouldBeNil)
  34. So(sql, ShouldEqual, "select 60000 ")
  35. })
  36. Convey("interpolate __unixEpochFrom function", func() {
  37. sql, err := Interpolate(query, timeRange, "select $__unixEpochFrom()")
  38. So(err, ShouldBeNil)
  39. So(sql, ShouldEqual, fmt.Sprintf("select %d", from.Unix()))
  40. })
  41. Convey("interpolate __unixEpochTo function", func() {
  42. sql, err := Interpolate(query, timeRange, "select $__unixEpochTo()")
  43. So(err, ShouldBeNil)
  44. So(sql, ShouldEqual, fmt.Sprintf("select %d", to.Unix()))
  45. })
  46. })
  47. Convey("Given row values with time.Time as time columns", func() {
  48. var nilPointer *time.Time
  49. fixtures := make([]interface{}, 5)
  50. fixtures[0] = dt
  51. fixtures[1] = &dt
  52. fixtures[2] = earlyDt
  53. fixtures[3] = &earlyDt
  54. fixtures[4] = nilPointer
  55. for i := range fixtures {
  56. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  57. }
  58. Convey("When converting them should return epoch time with millisecond precision ", func() {
  59. expected := float64(dt.UnixNano()) / float64(time.Millisecond)
  60. expectedEarly := float64(earlyDt.UnixNano()) / float64(time.Millisecond)
  61. So(fixtures[0].(float64), ShouldEqual, expected)
  62. So(fixtures[1].(float64), ShouldEqual, expected)
  63. So(fixtures[2].(float64), ShouldEqual, expectedEarly)
  64. So(fixtures[3].(float64), ShouldEqual, expectedEarly)
  65. So(fixtures[4], ShouldBeNil)
  66. })
  67. })
  68. Convey("Given row values with int64 as time columns", func() {
  69. tSeconds := dt.Unix()
  70. tMilliseconds := dt.UnixNano() / 1e6
  71. tNanoSeconds := dt.UnixNano()
  72. var nilPointer *int64
  73. fixtures := make([]interface{}, 7)
  74. fixtures[0] = tSeconds
  75. fixtures[1] = &tSeconds
  76. fixtures[2] = tMilliseconds
  77. fixtures[3] = &tMilliseconds
  78. fixtures[4] = tNanoSeconds
  79. fixtures[5] = &tNanoSeconds
  80. fixtures[6] = nilPointer
  81. for i := range fixtures {
  82. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  83. }
  84. Convey("When converting them should return epoch time with millisecond precision ", func() {
  85. So(fixtures[0].(int64), ShouldEqual, tSeconds*1e3)
  86. So(fixtures[1].(int64), ShouldEqual, tSeconds*1e3)
  87. So(fixtures[2].(int64), ShouldEqual, tMilliseconds)
  88. So(fixtures[3].(int64), ShouldEqual, tMilliseconds)
  89. So(fixtures[4].(int64), ShouldEqual, tMilliseconds)
  90. So(fixtures[5].(int64), ShouldEqual, tMilliseconds)
  91. So(fixtures[6], ShouldBeNil)
  92. })
  93. })
  94. Convey("Given row values with uin64 as time columns", func() {
  95. tSeconds := uint64(dt.Unix())
  96. tMilliseconds := uint64(dt.UnixNano() / 1e6)
  97. tNanoSeconds := uint64(dt.UnixNano())
  98. var nilPointer *uint64
  99. fixtures := make([]interface{}, 7)
  100. fixtures[0] = tSeconds
  101. fixtures[1] = &tSeconds
  102. fixtures[2] = tMilliseconds
  103. fixtures[3] = &tMilliseconds
  104. fixtures[4] = tNanoSeconds
  105. fixtures[5] = &tNanoSeconds
  106. fixtures[6] = nilPointer
  107. for i := range fixtures {
  108. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  109. }
  110. Convey("When converting them should return epoch time with millisecond precision ", func() {
  111. So(fixtures[0].(int64), ShouldEqual, tSeconds*1e3)
  112. So(fixtures[1].(int64), ShouldEqual, tSeconds*1e3)
  113. So(fixtures[2].(int64), ShouldEqual, tMilliseconds)
  114. So(fixtures[3].(int64), ShouldEqual, tMilliseconds)
  115. So(fixtures[4].(int64), ShouldEqual, tMilliseconds)
  116. So(fixtures[5].(int64), ShouldEqual, tMilliseconds)
  117. So(fixtures[6], ShouldBeNil)
  118. })
  119. })
  120. Convey("Given row values with int32 as time columns", func() {
  121. tSeconds := int32(dt.Unix())
  122. var nilInt *int32
  123. fixtures := make([]interface{}, 3)
  124. fixtures[0] = tSeconds
  125. fixtures[1] = &tSeconds
  126. fixtures[2] = nilInt
  127. for i := range fixtures {
  128. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  129. }
  130. Convey("When converting them should return epoch time with millisecond precision ", func() {
  131. So(fixtures[0].(int64), ShouldEqual, dt.Unix()*1e3)
  132. So(fixtures[1].(int64), ShouldEqual, dt.Unix()*1e3)
  133. So(fixtures[2], ShouldBeNil)
  134. })
  135. })
  136. Convey("Given row values with uint32 as time columns", func() {
  137. tSeconds := uint32(dt.Unix())
  138. var nilInt *uint32
  139. fixtures := make([]interface{}, 3)
  140. fixtures[0] = tSeconds
  141. fixtures[1] = &tSeconds
  142. fixtures[2] = nilInt
  143. for i := range fixtures {
  144. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  145. }
  146. Convey("When converting them should return epoch time with millisecond precision ", func() {
  147. So(fixtures[0].(int64), ShouldEqual, dt.Unix()*1e3)
  148. So(fixtures[1].(int64), ShouldEqual, dt.Unix()*1e3)
  149. So(fixtures[2], ShouldBeNil)
  150. })
  151. })
  152. Convey("Given row values with float64 as time columns", func() {
  153. tSeconds := float64(dt.UnixNano()) / float64(time.Second)
  154. tMilliseconds := float64(dt.UnixNano()) / float64(time.Millisecond)
  155. tNanoSeconds := float64(dt.UnixNano())
  156. var nilPointer *float64
  157. fixtures := make([]interface{}, 7)
  158. fixtures[0] = tSeconds
  159. fixtures[1] = &tSeconds
  160. fixtures[2] = tMilliseconds
  161. fixtures[3] = &tMilliseconds
  162. fixtures[4] = tNanoSeconds
  163. fixtures[5] = &tNanoSeconds
  164. fixtures[6] = nilPointer
  165. for i := range fixtures {
  166. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  167. }
  168. Convey("When converting them should return epoch time with millisecond precision ", func() {
  169. So(fixtures[0].(float64), ShouldEqual, tMilliseconds)
  170. So(fixtures[1].(float64), ShouldEqual, tMilliseconds)
  171. So(fixtures[2].(float64), ShouldEqual, tMilliseconds)
  172. So(fixtures[3].(float64), ShouldEqual, tMilliseconds)
  173. So(fixtures[4].(float64), ShouldEqual, tMilliseconds)
  174. So(fixtures[5].(float64), ShouldEqual, tMilliseconds)
  175. So(fixtures[6], ShouldBeNil)
  176. })
  177. })
  178. Convey("Given row values with float32 as time columns", func() {
  179. tSeconds := float32(dt.Unix())
  180. var nilInt *float32
  181. fixtures := make([]interface{}, 3)
  182. fixtures[0] = tSeconds
  183. fixtures[1] = &tSeconds
  184. fixtures[2] = nilInt
  185. for i := range fixtures {
  186. ConvertSqlTimeColumnToEpochMs(fixtures, i)
  187. }
  188. Convey("When converting them should return epoch time with millisecond precision ", func() {
  189. So(fixtures[0].(float64), ShouldEqual, float32(dt.Unix()*1e3))
  190. So(fixtures[1].(float64), ShouldEqual, float32(dt.Unix()*1e3))
  191. So(fixtures[2], ShouldBeNil)
  192. })
  193. })
  194. Convey("Given row with value columns", func() {
  195. intValue := 1
  196. int64Value := int64(1)
  197. int32Value := int32(1)
  198. int16Value := int16(1)
  199. int8Value := int8(1)
  200. float64Value := float64(1)
  201. float32Value := float32(1)
  202. uintValue := uint(1)
  203. uint64Value := uint64(1)
  204. uint32Value := uint32(1)
  205. uint16Value := uint16(1)
  206. uint8Value := uint8(1)
  207. fixtures := make([]interface{}, 24)
  208. fixtures[0] = intValue
  209. fixtures[1] = &intValue
  210. fixtures[2] = int64Value
  211. fixtures[3] = &int64Value
  212. fixtures[4] = int32Value
  213. fixtures[5] = &int32Value
  214. fixtures[6] = int16Value
  215. fixtures[7] = &int16Value
  216. fixtures[8] = int8Value
  217. fixtures[9] = &int8Value
  218. fixtures[10] = float64Value
  219. fixtures[11] = &float64Value
  220. fixtures[12] = float32Value
  221. fixtures[13] = &float32Value
  222. fixtures[14] = uintValue
  223. fixtures[15] = &uintValue
  224. fixtures[16] = uint64Value
  225. fixtures[17] = &uint64Value
  226. fixtures[18] = uint32Value
  227. fixtures[19] = &uint32Value
  228. fixtures[20] = uint16Value
  229. fixtures[21] = &uint16Value
  230. fixtures[22] = uint8Value
  231. fixtures[23] = &uint8Value
  232. var intNilPointer *int
  233. var int64NilPointer *int64
  234. var int32NilPointer *int32
  235. var int16NilPointer *int16
  236. var int8NilPointer *int8
  237. var float64NilPointer *float64
  238. var float32NilPointer *float32
  239. var uintNilPointer *uint
  240. var uint64NilPointer *uint64
  241. var uint32NilPointer *uint32
  242. var uint16NilPointer *uint16
  243. var uint8NilPointer *uint8
  244. nilPointerFixtures := make([]interface{}, 12)
  245. nilPointerFixtures[0] = intNilPointer
  246. nilPointerFixtures[1] = int64NilPointer
  247. nilPointerFixtures[2] = int32NilPointer
  248. nilPointerFixtures[3] = int16NilPointer
  249. nilPointerFixtures[4] = int8NilPointer
  250. nilPointerFixtures[5] = float64NilPointer
  251. nilPointerFixtures[6] = float32NilPointer
  252. nilPointerFixtures[7] = uintNilPointer
  253. nilPointerFixtures[8] = uint64NilPointer
  254. nilPointerFixtures[9] = uint32NilPointer
  255. nilPointerFixtures[10] = uint16NilPointer
  256. nilPointerFixtures[11] = uint8NilPointer
  257. Convey("When converting values to float should return expected value", func() {
  258. for _, f := range fixtures {
  259. value, _ := ConvertSqlValueColumnToFloat("col", f)
  260. if !value.Valid {
  261. t.Fatalf("Failed to convert %T value, expected a valid float value", f)
  262. }
  263. if value.Float64 != null.FloatFrom(1).Float64 {
  264. t.Fatalf("Failed to convert %T value, expected a float value of 1.000, but got %v", f, value)
  265. }
  266. }
  267. })
  268. Convey("When converting nil pointer values to float should return expected value", func() {
  269. for _, f := range nilPointerFixtures {
  270. value, err := ConvertSqlValueColumnToFloat("col", f)
  271. if err != nil {
  272. t.Fatalf("Failed to convert %T value, expected a non nil error, but got %v", f, err)
  273. }
  274. if value.Valid {
  275. t.Fatalf("Failed to convert %T value, expected an invalid float value", f)
  276. }
  277. }
  278. })
  279. })
  280. })
  281. }