funcs_ast_validator_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. package xsql
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "testing"
  7. )
  8. // Ensure the parser can parse strings into Statement ASTs.
  9. func TestFuncValidator(t *testing.T) {
  10. var tests = []struct {
  11. s string
  12. stmt *SelectStatement
  13. err string
  14. }{
  15. {
  16. s: `SELECT abs(1) FROM tbl`,
  17. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
  18. Sources: []Source{&Table{Name: "tbl"}},
  19. },
  20. },
  21. {
  22. s: `SELECT abs(field1) FROM tbl`,
  23. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&FieldRef{Name: "field1"}}}}},
  24. Sources: []Source{&Table{Name: "tbl"}},
  25. },
  26. },
  27. {
  28. s: `SELECT abs(1,2) FROM tbl`,
  29. stmt: nil,
  30. err: "The arguments for abs should be 1.",
  31. },
  32. {
  33. s: `SELECT abs(1.1) FROM tbl`,
  34. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "abs", Expr: &Call{Name: "abs", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
  35. Sources: []Source{&Table{Name: "tbl"}},
  36. },
  37. },
  38. {
  39. s: `SELECT abs(true) FROM tbl`,
  40. stmt: nil,
  41. err: "Expect number - float or int type for 1 parameter of function abs.",
  42. },
  43. {
  44. s: `SELECT abs("test") FROM tbl`,
  45. stmt: nil,
  46. err: "Expect number - float or int type for 1 parameter of function abs.",
  47. },
  48. {
  49. s: `SELECT abs(ss) FROM tbl`,
  50. stmt: nil,
  51. err: "Expect number - float or int type for 1 parameter of function abs.",
  52. },
  53. ///
  54. {
  55. s: `SELECT sin(1) FROM tbl`,
  56. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sin", Expr: &Call{Name: "sin", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
  57. Sources: []Source{&Table{Name: "tbl"}},
  58. },
  59. },
  60. {
  61. s: `SELECT sin(1.1) FROM tbl`,
  62. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sin", Expr: &Call{Name: "sin", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
  63. Sources: []Source{&Table{Name: "tbl"}},
  64. },
  65. },
  66. {
  67. s: `SELECT sin(true) FROM tbl`,
  68. stmt: nil,
  69. err: "Expect number - float or int type for 1 parameter of function sin.",
  70. },
  71. {
  72. s: `SELECT sin("test") FROM tbl`,
  73. stmt: nil,
  74. err: "Expect number - float or int type for 1 parameter of function sin.",
  75. },
  76. {
  77. s: `SELECT sin(ss) FROM tbl`,
  78. stmt: nil,
  79. err: "Expect number - float or int type for 1 parameter of function sin.",
  80. },
  81. ///
  82. {
  83. s: `SELECT tanh(1) FROM tbl`,
  84. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "tanh", Expr: &Call{Name: "tanh", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
  85. Sources: []Source{&Table{Name: "tbl"}},
  86. },
  87. },
  88. {
  89. s: `SELECT tanh(1.1) FROM tbl`,
  90. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "tanh", Expr: &Call{Name: "tanh", Args: []Expr{&NumberLiteral{Val: 1.1}}}}},
  91. Sources: []Source{&Table{Name: "tbl"}},
  92. },
  93. },
  94. {
  95. s: `SELECT tanh(true) FROM tbl`,
  96. stmt: nil,
  97. err: "Expect number - float or int type for 1 parameter of function tanh.",
  98. },
  99. {
  100. s: `SELECT tanh("test") FROM tbl`,
  101. stmt: nil,
  102. err: "Expect number - float or int type for 1 parameter of function tanh.",
  103. },
  104. {
  105. s: `SELECT tanh(ss) FROM tbl`,
  106. stmt: nil,
  107. err: "Expect number - float or int type for 1 parameter of function tanh.",
  108. },
  109. ///
  110. {
  111. s: `SELECT bitxor(1, 2) FROM tbl`,
  112. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "bitxor", Expr: &Call{Name: "bitxor", Args: []Expr{&IntegerLiteral{Val: 1}, &IntegerLiteral{Val: 2}}}}},
  113. Sources: []Source{&Table{Name: "tbl"}},
  114. },
  115. },
  116. {
  117. s: `SELECT bitxor(1.1, 2) FROM tbl`,
  118. stmt: nil,
  119. err: "Expect int type for 1 parameter of function bitxor.",
  120. },
  121. {
  122. s: `SELECT bitxor(true, 2) FROM tbl`,
  123. stmt: nil,
  124. err: "Expect int type for 1 parameter of function bitxor.",
  125. },
  126. {
  127. s: `SELECT bitxor(1, ss) FROM tbl`,
  128. stmt: nil,
  129. err: "Expect int type for 2 parameter of function bitxor.",
  130. },
  131. {
  132. s: `SELECT bitxor(1, 2.2) FROM tbl`,
  133. stmt: nil,
  134. err: "Expect int type for 2 parameter of function bitxor.",
  135. },
  136. ///
  137. {
  138. s: `SELECT bitnot(1) FROM tbl`,
  139. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "bitnot", Expr: &Call{Name: "bitnot", Args: []Expr{&IntegerLiteral{Val: 1}}}}},
  140. Sources: []Source{&Table{Name: "tbl"}},
  141. },
  142. },
  143. {
  144. s: `SELECT bitnot(1.1) FROM tbl`,
  145. stmt: nil,
  146. err: "Expect int type for 1 parameter of function bitnot.",
  147. },
  148. {
  149. s: `SELECT bitnot(true) FROM tbl`,
  150. stmt: nil,
  151. err: "Expect int type for 1 parameter of function bitnot.",
  152. },
  153. ///
  154. {
  155. s: `SELECT mod(1, 2) FROM tbl`,
  156. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "mod", Expr: &Call{Name: "mod", Args: []Expr{&IntegerLiteral{Val: 1}, &IntegerLiteral{Val: 2}}}}},
  157. Sources: []Source{&Table{Name: "tbl"}},
  158. },
  159. },
  160. {
  161. s: `SELECT mod("1.1", 2) FROM tbl`,
  162. stmt: nil,
  163. err: "Expect number - float or int type for 1 parameter of function mod.",
  164. },
  165. {
  166. s: `SELECT mod(1.1, true) FROM tbl`,
  167. stmt: nil,
  168. err: "Expect number - float or int type for 2 parameter of function mod.",
  169. },
  170. {
  171. s: `SELECT mod(1, ss) FROM tbl`,
  172. stmt: nil,
  173. err: "Expect number - float or int type for 2 parameter of function mod.",
  174. },
  175. ///
  176. {
  177. s: `SELECT concat(field, "hello") FROM tbl`,
  178. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "concat", Expr: &Call{Name: "concat", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}}}}},
  179. Sources: []Source{&Table{Name: "tbl"}},
  180. },
  181. },
  182. {
  183. s: `SELECT concat("1.1", 2) FROM tbl`,
  184. stmt: nil,
  185. err: "Expect string type for 2 parameter of function concat.",
  186. },
  187. {
  188. s: `SELECT concat("1.1", true) FROM tbl`,
  189. stmt: nil,
  190. err: "Expect string type for 2 parameter of function concat.",
  191. },
  192. {
  193. s: `SELECT concat("1", ss) FROM tbl`,
  194. stmt: nil,
  195. err: "Expect string type for 2 parameter of function concat.",
  196. },
  197. ///
  198. {
  199. s: `SELECT regexp_matches(field, "hello") FROM tbl`,
  200. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "regexp_matches", Expr: &Call{Name: "regexp_matches", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}}}}},
  201. Sources: []Source{&Table{Name: "tbl"}},
  202. },
  203. },
  204. {
  205. s: `SELECT regexp_matches(1, "true") FROM tbl`,
  206. stmt: nil,
  207. err: "Expect string type for 1 parameter of function regexp_matches.",
  208. },
  209. {
  210. s: `SELECT regexp_matches("1.1", 2) FROM tbl`,
  211. stmt: nil,
  212. err: "Expect string type for 2 parameter of function regexp_matches.",
  213. },
  214. ///
  215. {
  216. s: `SELECT regexp_replace(field, "hello", "h") FROM tbl`,
  217. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "regexp_replace", Expr: &Call{Name: "regexp_replace", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "hello"}, &StringLiteral{Val: "h"}}}}},
  218. Sources: []Source{&Table{Name: "tbl"}},
  219. },
  220. },
  221. {
  222. s: `SELECT regexp_replace(field1, "true", true) FROM tbl`,
  223. stmt: nil,
  224. err: "Expect string type for 3 parameter of function regexp_replace.",
  225. },
  226. ///
  227. {
  228. s: `SELECT trim(field) FROM tbl`,
  229. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "trim", Expr: &Call{Name: "trim", Args: []Expr{&FieldRef{Name: "field"}}}}},
  230. Sources: []Source{&Table{Name: "tbl"}},
  231. },
  232. },
  233. {
  234. s: `SELECT trim(1) FROM tbl`,
  235. stmt: nil,
  236. err: "Expect string type for 1 parameter of function trim.",
  237. },
  238. ///
  239. {
  240. s: `SELECT rpad(field, 3) FROM tbl`,
  241. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "rpad", Expr: &Call{Name: "rpad", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}}}}},
  242. Sources: []Source{&Table{Name: "tbl"}},
  243. },
  244. },
  245. {
  246. s: `SELECT rpad("ff", true) FROM tbl`,
  247. stmt: nil,
  248. err: "Expect int type for 2 parameter of function rpad.",
  249. },
  250. ///
  251. {
  252. s: `SELECT substring(field, 3, 4) FROM tbl`,
  253. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "substring", Expr: &Call{Name: "substring", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}, &IntegerLiteral{Val: 4}}}}},
  254. Sources: []Source{&Table{Name: "tbl"}},
  255. },
  256. },
  257. {
  258. s: `SELECT substring(field, -1, 4) FROM tbl`,
  259. stmt: nil,
  260. err: "The start index should not be a nagtive integer.",
  261. },
  262. {
  263. s: `SELECT substring(field, 0, -1) FROM tbl`,
  264. stmt: nil,
  265. err: "The end index should be larger than start index.",
  266. },
  267. {
  268. s: `SELECT substring(field, 0, true) FROM tbl`,
  269. stmt: nil,
  270. err: "Expect int type for 3 parameter of function substring.",
  271. },
  272. ///
  273. {
  274. s: `SELECT cast(field, "bigint") FROM tbl`,
  275. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "cast", Expr: &Call{Name: "cast", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "bigint"}}}}},
  276. Sources: []Source{&Table{Name: "tbl"}},
  277. },
  278. },
  279. {
  280. s: `SELECT cast("12", "bool") FROM tbl`,
  281. stmt: nil,
  282. err: "Expect one of following value for the 2nd parameter: bigint, float, string, boolean, datetime.",
  283. },
  284. ///
  285. {
  286. s: `SELECT chr(field) FROM tbl`,
  287. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "chr", Expr: &Call{Name: "chr", Args: []Expr{&FieldRef{Name: "field"}}}}},
  288. Sources: []Source{&Table{Name: "tbl"}},
  289. },
  290. },
  291. {
  292. s: `SELECT chr(true) FROM tbl`,
  293. stmt: nil,
  294. err: "Expect int type for 1 parameter of function chr.",
  295. },
  296. ///
  297. {
  298. s: `SELECT encode(field, "base64") FROM tbl`,
  299. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "encode", Expr: &Call{Name: "encode", Args: []Expr{&FieldRef{Name: "field"}, &StringLiteral{Val: "base64"}}}}},
  300. Sources: []Source{&Table{Name: "tbl"}},
  301. },
  302. },
  303. {
  304. s: `SELECT encode(field, true) FROM tbl`,
  305. stmt: nil,
  306. err: "Expect string type for 2 parameter of function encode.",
  307. },
  308. ///
  309. {
  310. s: `SELECT trunc(field, 3) FROM tbl`,
  311. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "trunc", Expr: &Call{Name: "trunc", Args: []Expr{&FieldRef{Name: "field"}, &IntegerLiteral{Val: 3}}}}},
  312. Sources: []Source{&Table{Name: "tbl"}},
  313. },
  314. },
  315. {
  316. s: `SELECT trunc(5, ss) FROM tbl`,
  317. stmt: nil,
  318. err: "Expect int type for 2 parameter of function trunc.",
  319. },
  320. ///
  321. {
  322. s: `SELECT sha512(field) FROM tbl`,
  323. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "sha512", Expr: &Call{Name: "sha512", Args: []Expr{&FieldRef{Name: "field"}}}}},
  324. Sources: []Source{&Table{Name: "tbl"}},
  325. },
  326. },
  327. {
  328. s: `SELECT sha512(20) FROM tbl`,
  329. stmt: nil,
  330. err: "Expect string type for 1 parameter of function sha512.",
  331. },
  332. {
  333. s: `SELECT mqtt("topic") FROM tbl`,
  334. stmt: nil,
  335. err: "Expect meta reference type for 1 parameter of function mqtt.",
  336. },
  337. {
  338. s: `SELECT mqtt(topic1) FROM tbl`,
  339. stmt: nil,
  340. err: "Parameter of mqtt function can be only topic or messageid.",
  341. },
  342. {
  343. s: `SELECT split_value(topic1) FROM tbl`,
  344. stmt: nil,
  345. err: "the arguments for split_value should be 3",
  346. },
  347. {
  348. s: `SELECT split_value(topic1, 3, 1) FROM tbl`,
  349. stmt: nil,
  350. err: "Expect string type for 2 parameter of function split_value.",
  351. },
  352. {
  353. s: `SELECT split_value(topic1, "hello", -1) FROM tbl`,
  354. stmt: nil,
  355. err: "The index should not be a nagtive integer.",
  356. },
  357. {
  358. s: `SELECT meta(tbl, "timestamp", 1) FROM tbl`,
  359. stmt: nil,
  360. err: "The arguments for meta should be 1.",
  361. },
  362. {
  363. s: `SELECT meta("src1.device") FROM tbl`,
  364. stmt: nil,
  365. err: "Expect meta reference type for 1 parameter of function meta.",
  366. },
  367. {
  368. s: `SELECT meta(device) FROM tbl`,
  369. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "meta", Expr: &Call{Name: "meta", Args: []Expr{&MetaRef{Name: "device"}}}}}, Sources: []Source{&Table{Name: "tbl"}}},
  370. },
  371. {
  372. s: `SELECT meta(tbl.device) FROM tbl`,
  373. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "meta", Expr: &Call{Name: "meta", Args: []Expr{&MetaRef{StreamName: "tbl", Name: "device"}}}}}, Sources: []Source{&Table{Name: "tbl"}}},
  374. },
  375. {
  376. s: `SELECT meta(device->reading->topic) FROM tbl`,
  377. stmt: &SelectStatement{Fields: []Field{{AName: "", Name: "meta", Expr: &Call{Name: "meta", Args: []Expr{&BinaryExpr{
  378. OP: ARROW,
  379. LHS: &BinaryExpr{
  380. OP: ARROW,
  381. LHS: &MetaRef{Name: "device"},
  382. RHS: &MetaRef{Name: "reading"},
  383. },
  384. RHS: &MetaRef{Name: "topic"},
  385. }}}}}, Sources: []Source{&Table{Name: "tbl"}}},
  386. },
  387. {
  388. s: `SELECT json_path_query(data, 44) AS data
  389. FROM characters;`,
  390. stmt: nil,
  391. err: "Expect string type for 2 parameter of function json_path_query.",
  392. },
  393. }
  394. fmt.Printf("The test bucket size is %d.\n\n", len(tests))
  395. for i, tt := range tests {
  396. //fmt.Printf("Parsing SQL %q.\n", tt.s)
  397. stmt, err := NewParser(strings.NewReader(tt.s)).Parse()
  398. if !reflect.DeepEqual(tt.err, errstring(err)) {
  399. t.Errorf("%d. %q: error mismatch:\n exp=%s\n got=%s\n\n", i, tt.s, tt.err, err)
  400. } else if tt.err == "" && !reflect.DeepEqual(tt.stmt, stmt) {
  401. t.Errorf("%d. %q\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.s, tt.stmt, stmt)
  402. }
  403. }
  404. }