funcs_ast_validator_test.go 14 KB

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