sql_engine_test.go 11 KB

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