funcs_ast_validator.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // Copyright 2021 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package function
  15. import (
  16. "fmt"
  17. "github.com/lf-edge/ekuiper/pkg/ast"
  18. "strings"
  19. )
  20. type AllowTypes struct {
  21. types []ast.Literal
  22. }
  23. func validateFuncs(funcName string, args []ast.Expr) error {
  24. lowerName := strings.ToLower(funcName)
  25. switch getFuncType(lowerName) {
  26. case AggFunc:
  27. return validateAggFunc(lowerName, args)
  28. case MathFunc:
  29. return validateMathFunc(lowerName, args)
  30. case ConvFunc:
  31. return validateConvFunc(lowerName, args)
  32. case StrFunc:
  33. return validateStrFunc(lowerName, args)
  34. case HashFunc:
  35. return validateHashFunc(lowerName, args)
  36. case JsonFunc:
  37. return validateJsonFunc(lowerName, args)
  38. case OtherFunc:
  39. return validateOtherFunc(lowerName, args)
  40. default:
  41. // should not happen
  42. return fmt.Errorf("unkndow function %s", lowerName)
  43. }
  44. }
  45. func validateMathFunc(name string, args []ast.Expr) error {
  46. len := len(args)
  47. switch name {
  48. case "abs", "acos", "asin", "atan", "ceil", "cos", "cosh", "exp", "ln", "log", "round", "sign", "sin", "sinh",
  49. "sqrt", "tan", "tanh":
  50. if err := ast.ValidateLen(name, 1, len); err != nil {
  51. return err
  52. }
  53. if ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  54. return ast.ProduceErrInfo(name, 0, "number - float or int")
  55. }
  56. case "bitand", "bitor", "bitxor":
  57. if err := ast.ValidateLen(name, 2, len); err != nil {
  58. return err
  59. }
  60. if ast.IsFloatArg(args[0]) || ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  61. return ast.ProduceErrInfo(name, 0, "int")
  62. }
  63. if ast.IsFloatArg(args[1]) || ast.IsStringArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) {
  64. return ast.ProduceErrInfo(name, 1, "int")
  65. }
  66. case "bitnot":
  67. if err := ast.ValidateLen(name, 1, len); err != nil {
  68. return err
  69. }
  70. if ast.IsFloatArg(args[0]) || ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  71. return ast.ProduceErrInfo(name, 0, "int")
  72. }
  73. case "atan2", "mod", "power":
  74. if err := ast.ValidateLen(name, 2, len); err != nil {
  75. return err
  76. }
  77. if ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  78. return ast.ProduceErrInfo(name, 0, "number - float or int")
  79. }
  80. if ast.IsStringArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) {
  81. return ast.ProduceErrInfo(name, 1, "number - float or int")
  82. }
  83. case "rand":
  84. if err := ast.ValidateLen(name, 0, len); err != nil {
  85. return err
  86. }
  87. }
  88. return nil
  89. }
  90. func validateStrFunc(name string, args []ast.Expr) error {
  91. len := len(args)
  92. switch name {
  93. case "concat":
  94. if len == 0 {
  95. return fmt.Errorf("The arguments for %s should be at least one.\n", name)
  96. }
  97. for i, a := range args {
  98. if ast.IsNumericArg(a) || ast.IsTimeArg(a) || ast.IsBooleanArg(a) {
  99. return ast.ProduceErrInfo(name, i, "string")
  100. }
  101. }
  102. case "endswith", "indexof", "regexp_matches", "startswith":
  103. if err := ast.ValidateLen(name, 2, len); err != nil {
  104. return err
  105. }
  106. for i := 0; i < 2; i++ {
  107. if ast.IsNumericArg(args[i]) || ast.IsTimeArg(args[i]) || ast.IsBooleanArg(args[i]) {
  108. return ast.ProduceErrInfo(name, i, "string")
  109. }
  110. }
  111. case "format_time":
  112. if err := ast.ValidateLen(name, 2, len); err != nil {
  113. return err
  114. }
  115. if ast.IsNumericArg(args[0]) || ast.IsStringArg(args[0]) || ast.IsBooleanArg(args[0]) {
  116. return ast.ProduceErrInfo(name, 0, "datetime")
  117. }
  118. if ast.IsNumericArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) {
  119. return ast.ProduceErrInfo(name, 1, "string")
  120. }
  121. case "regexp_replace":
  122. if err := ast.ValidateLen(name, 3, len); err != nil {
  123. return err
  124. }
  125. for i := 0; i < 3; i++ {
  126. if ast.IsNumericArg(args[i]) || ast.IsTimeArg(args[i]) || ast.IsBooleanArg(args[i]) {
  127. return ast.ProduceErrInfo(name, i, "string")
  128. }
  129. }
  130. case "length", "lower", "ltrim", "numbytes", "rtrim", "trim", "upper":
  131. if err := ast.ValidateLen(name, 1, len); err != nil {
  132. return err
  133. }
  134. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  135. return ast.ProduceErrInfo(name, 0, "string")
  136. }
  137. case "lpad", "rpad":
  138. if err := ast.ValidateLen(name, 2, len); err != nil {
  139. return err
  140. }
  141. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  142. return ast.ProduceErrInfo(name, 0, "string")
  143. }
  144. if ast.IsFloatArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) || ast.IsStringArg(args[1]) {
  145. return ast.ProduceErrInfo(name, 1, "int")
  146. }
  147. case "substring":
  148. if len != 2 && len != 3 {
  149. return fmt.Errorf("the arguments for substring should be 2 or 3")
  150. }
  151. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  152. return ast.ProduceErrInfo(name, 0, "string")
  153. }
  154. for i := 1; i < len; i++ {
  155. if ast.IsFloatArg(args[i]) || ast.IsTimeArg(args[i]) || ast.IsBooleanArg(args[i]) || ast.IsStringArg(args[i]) {
  156. return ast.ProduceErrInfo(name, i, "int")
  157. }
  158. }
  159. if s, ok := args[1].(*ast.IntegerLiteral); ok {
  160. sv := s.Val
  161. if sv < 0 {
  162. return fmt.Errorf("The start index should not be a nagtive integer.")
  163. }
  164. if len == 3 {
  165. if e, ok1 := args[2].(*ast.IntegerLiteral); ok1 {
  166. ev := e.Val
  167. if ev < sv {
  168. return fmt.Errorf("The end index should be larger than start index.")
  169. }
  170. }
  171. }
  172. }
  173. case "split_value":
  174. if len != 3 {
  175. return fmt.Errorf("the arguments for split_value should be 3")
  176. }
  177. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  178. return ast.ProduceErrInfo(name, 0, "string")
  179. }
  180. if ast.IsNumericArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) {
  181. return ast.ProduceErrInfo(name, 1, "string")
  182. }
  183. if ast.IsFloatArg(args[2]) || ast.IsTimeArg(args[2]) || ast.IsBooleanArg(args[2]) || ast.IsStringArg(args[2]) {
  184. return ast.ProduceErrInfo(name, 2, "int")
  185. }
  186. if s, ok := args[2].(*ast.IntegerLiteral); ok {
  187. if s.Val < 0 {
  188. return fmt.Errorf("The index should not be a nagtive integer.")
  189. }
  190. }
  191. }
  192. return nil
  193. }
  194. func validateConvFunc(name string, args []ast.Expr) error {
  195. len := len(args)
  196. switch name {
  197. case "cast":
  198. if err := ast.ValidateLen(name, 2, len); err != nil {
  199. return err
  200. }
  201. a := args[1]
  202. if !ast.IsStringArg(a) {
  203. return ast.ProduceErrInfo(name, 1, "string")
  204. }
  205. if av, ok := a.(*ast.StringLiteral); ok {
  206. if !(av.Val == "bigint" || av.Val == "float" || av.Val == "string" || av.Val == "boolean" || av.Val == "datetime") {
  207. return fmt.Errorf("Expect one of following value for the 2nd parameter: bigint, float, string, boolean, datetime.")
  208. }
  209. }
  210. case "chr":
  211. if err := ast.ValidateLen(name, 1, len); err != nil {
  212. return err
  213. }
  214. if ast.IsFloatArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  215. return ast.ProduceErrInfo(name, 0, "int")
  216. }
  217. case "encode":
  218. if err := ast.ValidateLen(name, 2, len); err != nil {
  219. return err
  220. }
  221. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  222. return ast.ProduceErrInfo(name, 0, "string")
  223. }
  224. a := args[1]
  225. if !ast.IsStringArg(a) {
  226. return ast.ProduceErrInfo(name, 1, "string")
  227. }
  228. if av, ok := a.(*ast.StringLiteral); ok {
  229. if av.Val != "base64" {
  230. return fmt.Errorf("Only base64 is supported for the 2nd parameter.")
  231. }
  232. }
  233. case "trunc":
  234. if err := ast.ValidateLen(name, 2, len); err != nil {
  235. return err
  236. }
  237. if ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) || ast.IsStringArg(args[0]) {
  238. return ast.ProduceErrInfo(name, 0, "number - float or int")
  239. }
  240. if ast.IsFloatArg(args[1]) || ast.IsTimeArg(args[1]) || ast.IsBooleanArg(args[1]) || ast.IsStringArg(args[1]) {
  241. return ast.ProduceErrInfo(name, 1, "int")
  242. }
  243. }
  244. return nil
  245. }
  246. func validateHashFunc(name string, args []ast.Expr) error {
  247. len := len(args)
  248. switch name {
  249. case "md5", "sha1", "sha224", "sha256", "sha384", "sha512":
  250. if err := ast.ValidateLen(name, 1, len); err != nil {
  251. return err
  252. }
  253. if ast.IsNumericArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  254. return ast.ProduceErrInfo(name, 0, "string")
  255. }
  256. }
  257. return nil
  258. }
  259. func validateOtherFunc(name string, args []ast.Expr) error {
  260. len := len(args)
  261. switch name {
  262. case "isNull":
  263. if err := ast.ValidateLen(name, 1, len); err != nil {
  264. return err
  265. }
  266. case "cardinality":
  267. if err := ast.ValidateLen(name, 1, len); err != nil {
  268. return err
  269. }
  270. case "nanvl":
  271. if err := ast.ValidateLen(name, 2, len); err != nil {
  272. return err
  273. }
  274. if ast.IsIntegerArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) || ast.IsStringArg(args[0]) {
  275. return ast.ProduceErrInfo(name, 1, "float")
  276. }
  277. case "newuuid":
  278. if err := ast.ValidateLen(name, 0, len); err != nil {
  279. return err
  280. }
  281. case "mqtt":
  282. if err := ast.ValidateLen(name, 1, len); err != nil {
  283. return err
  284. }
  285. if ast.IsIntegerArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) || ast.IsStringArg(args[0]) || ast.IsFloatArg(args[0]) {
  286. return ast.ProduceErrInfo(name, 0, "meta reference")
  287. }
  288. if p, ok := args[0].(*ast.MetaRef); ok {
  289. name := strings.ToLower(p.Name)
  290. if name != "topic" && name != "messageid" {
  291. return fmt.Errorf("Parameter of mqtt function can be only topic or messageid.")
  292. }
  293. }
  294. case "meta":
  295. if err := ast.ValidateLen(name, 1, len); err != nil {
  296. return err
  297. }
  298. if _, ok := args[0].(*ast.MetaRef); ok {
  299. return nil
  300. }
  301. expr := args[0]
  302. for {
  303. if be, ok := expr.(*ast.BinaryExpr); ok {
  304. if _, ok := be.LHS.(*ast.MetaRef); ok && be.OP == ast.ARROW {
  305. return nil
  306. }
  307. expr = be.LHS
  308. } else {
  309. break
  310. }
  311. }
  312. return ast.ProduceErrInfo(name, 0, "meta reference")
  313. }
  314. return nil
  315. }
  316. func validateJsonFunc(name string, args []ast.Expr) error {
  317. len := len(args)
  318. if err := ast.ValidateLen(name, 2, len); err != nil {
  319. return err
  320. }
  321. if !ast.IsStringArg(args[1]) {
  322. return ast.ProduceErrInfo(name, 1, "string")
  323. }
  324. return nil
  325. }
  326. func validateAggFunc(name string, args []ast.Expr) error {
  327. len := len(args)
  328. switch name {
  329. case "avg", "max", "min", "sum":
  330. if err := ast.ValidateLen(name, 1, len); err != nil {
  331. return err
  332. }
  333. if ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  334. return ast.ProduceErrInfo(name, 0, "number - float or int")
  335. }
  336. case "count":
  337. if err := ast.ValidateLen(name, 1, len); err != nil {
  338. return err
  339. }
  340. case "collect":
  341. if err := ast.ValidateLen(name, 1, len); err != nil {
  342. return err
  343. }
  344. case "deduplicate":
  345. if err := ast.ValidateLen(name, 2, len); err != nil {
  346. return err
  347. }
  348. if !ast.IsBooleanArg(args[1]) {
  349. return ast.ProduceErrInfo(name, 1, "bool")
  350. }
  351. }
  352. return nil
  353. }