mqls_action.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. package odbcmql
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math"
  6. "regexp"
  7. "strings"
  8. "time"
  9. "git.wecise.com/wecise/odb-go/odb"
  10. "git.wecise.com/wecise/odb-go/odb/mql/parser"
  11. "git.wecise.com/wecise/odb-go/odb/mql/qstru"
  12. "gitee.com/wecisecode/util/cast"
  13. "gitee.com/wecisecode/util/merrs"
  14. "gitee.com/wecisecode/util/mfmt"
  15. "gitee.com/wecisecode/util/set/strset"
  16. "gitee.com/wecisecode/util/sortedmap"
  17. )
  18. type Action struct {
  19. ID int
  20. Name string
  21. Args []interface{}
  22. SourceFromIndex int
  23. SourceToIndex int
  24. SourceText string //
  25. }
  26. type OnErrorProc int
  27. const (
  28. OnErrorHalt OnErrorProc = iota // halt, fail, exit
  29. OnErrorIgnore // continue, ignore
  30. OnErrorBreak // break, 中断循环
  31. OnErrorPass // expect, pass, need, sure
  32. )
  33. type StaticActions struct {
  34. Skip bool
  35. RetryLimit int
  36. Scope string
  37. Qmeta odb.QueryMeta
  38. Timeout *time.Duration
  39. LoopCount *int
  40. LoopFrom *int
  41. LoopStep *int
  42. ParallelCount *int
  43. ForkName *string
  44. WaitName *string
  45. SleepTime *time.Duration
  46. Variables map[string]interface{}
  47. BeforeRunActions []*Action
  48. }
  49. type DynamicActions struct {
  50. SubscribeArgs []string
  51. UnsubscribeArgs []string
  52. Params string
  53. }
  54. type OnErrorOption struct {
  55. regex map[OnErrorProc]*regexp.Regexp
  56. noerrorinfo bool
  57. }
  58. type ActionExprs struct {
  59. *sortedmap.LinkedMap
  60. staticActions *StaticActions
  61. dynamicActions *DynamicActions
  62. followThroughActions []*Action
  63. onerrorOption *OnErrorOption
  64. }
  65. func getActionExprs(mqlstr string, staticactions map[int]*Action) (actionexprs *ActionExprs, err error) {
  66. defer func() {
  67. if err != nil {
  68. err = merrs.New(err, merrs.Map{"mql": mqlstr})
  69. }
  70. }()
  71. actionexprs = &ActionExprs{
  72. LinkedMap: sortedmap.NewLinkedMap(),
  73. onerrorOption: &OnErrorOption{
  74. regex: map[OnErrorProc]*regexp.Regexp{},
  75. },
  76. }
  77. {
  78. // /** ... **/ 之间的内容
  79. qlsindex := reactioneexprs.FindStringSubmatchIndex(mqlstr)
  80. if len(qlsindex) < 4 {
  81. // --{ ... } 之间的内容
  82. qlsindex = reactioneexprs_2.FindStringSubmatchIndex(mqlstr)
  83. if len(qlsindex) < 4 {
  84. // --{ ... } 之间的内容
  85. qlsindex = reactioneexprs_3.FindStringSubmatchIndex(mqlstr)
  86. if len(qlsindex) < 4 {
  87. return
  88. }
  89. }
  90. }
  91. isactionexpr := qlsindex[2]
  92. ieactionexpr := qlsindex[3]
  93. if isactionexpr < 0 || ieactionexpr < 0 {
  94. return
  95. }
  96. sactionexpr := mqlstr[isactionexpr:ieactionexpr]
  97. runestart := len([]rune(mqlstr[:isactionexpr]))
  98. // for i, q := range qls {
  99. // if i == len(qls)-1 {
  100. // break
  101. // }
  102. // if i > 0 {
  103. // isactionexpr += 2
  104. // }
  105. // isactionexpr += len(q)
  106. // }
  107. // ckfs := strings.TrimSpace(qls[len(qls)-1])
  108. // if len(ckfs) > 2 && ckfs[0] == '{' && ckfs[len(ckfs)-1] == '}' {
  109. // sactionexpr = ckfs[1 : len(ckfs)-1]
  110. // }
  111. if sactionexpr != "" {
  112. // 解析动作表达式,构建动作对象
  113. // 对应 odo-go/odb/mql/parser/grammar/mql.peg.txt 语法中的 Functions 部分
  114. stmts, mp, e := parser.ParseMQL(sactionexpr)
  115. if e != nil {
  116. // logger.Error(e)
  117. return nil, e
  118. }
  119. ab := &ActionBuilder{
  120. runestart: runestart,
  121. actionid: 0,
  122. staticactions: staticactions,
  123. actionexprs: actionexprs,
  124. }
  125. for _, stmt := range stmts {
  126. fields := stmt.(*qstru.SelectStatement).Fields
  127. for _, sf := range fields {
  128. sp := mp.SourcePosition()[sf]
  129. if len(sp) != 1 {
  130. panic("len(sp) != 1,一个字段有且只有一个确定位置")
  131. }
  132. source := mp.Source(sp[0])
  133. ab.NewAction(sf.Expr, sp[0], source)
  134. }
  135. }
  136. }
  137. }
  138. return
  139. }
  140. type ActionBuilder struct {
  141. runestart int
  142. actionid int
  143. staticactions map[int]*Action
  144. actionexprs *ActionExprs
  145. }
  146. func (ab *ActionBuilder) NewAction(sfe *qstru.Expr, sp parser.SourcePosition, source string) *Action {
  147. ab.actionid++
  148. if act := ab.staticactions[ab.actionid]; act != nil {
  149. ab.actionexprs.Put(act.Name, act)
  150. return act
  151. }
  152. action := fmt.Sprint(sfe.FuncName)
  153. fargs := sfe.FuncArgs
  154. sargs := []interface{}{}
  155. for _, farg := range fargs {
  156. if farg == nil {
  157. sargs = append(sargs, nil)
  158. } else if farg.Const != nil {
  159. sargs = append(sargs, farg.Const)
  160. } else if len(farg.VarName) != 0 && farg.VarName[0] != "" {
  161. sargs = append(sargs, farg)
  162. } else if farg.FuncName != nil && farg.FuncArgs != nil {
  163. sargs = append(sargs, ab.NewAction(farg, parser.SourcePosition{}, ""))
  164. } else {
  165. sargs = append(sargs, nil)
  166. }
  167. }
  168. act := &Action{
  169. ID: ab.actionid,
  170. Name: action,
  171. Args: sargs,
  172. SourceFromIndex: sp.Begin + ab.runestart,
  173. SourceToIndex: sp.End + ab.runestart,
  174. SourceText: source,
  175. }
  176. ab.actionexprs.Put(act.Name, act)
  177. // 记录在mql中的位置,避免固定数值设定被动态改变
  178. if STATIC_ACTION_NAMES.Has(action) {
  179. ab.staticactions[ab.actionid] = act
  180. }
  181. if FOLLOWTHROUGH_ACTION_NAMES.Has(act.Name) {
  182. ab.actionexprs.followThroughActions = append(ab.actionexprs.followThroughActions, act)
  183. }
  184. if ONERROR_ACTION_NAMES.Has(action) {
  185. switch action {
  186. case "noerrinfo":
  187. ab.actionexprs.onerrorOption.noerrorinfo = true
  188. case "onerror":
  189. if len(act.Args) > 0 {
  190. oep := OnErrorHalt
  191. switch cast.ToString(act.Args[0]) {
  192. case "break":
  193. oep = OnErrorBreak
  194. case "continue", "ignore":
  195. oep = OnErrorIgnore
  196. case "pass", "expect", "need", "must", "sure":
  197. oep = OnErrorPass
  198. case "fail", "halt", "exit":
  199. default:
  200. }
  201. msgs := []string{}
  202. for _, arg := range act.Args[1:] {
  203. sarg := cast.ToString(arg)
  204. if sarg != "" {
  205. msgs = append(msgs, sarg)
  206. }
  207. }
  208. msg := strings.Join(msgs, "|")
  209. msg = regexp.MustCompile("([^\\|\\*0-9A-Z_a-z\u0100-\uffff])").ReplaceAllString(msg, "\\$1")
  210. msg = strings.ReplaceAll(msg, "*", ".*")
  211. var regx *regexp.Regexp
  212. if msg == "" {
  213. regx = matchall
  214. } else {
  215. msg = "(?:" + strings.ReplaceAll(msg, "|", ")|(?:") + ")"
  216. regx = ab.actionexprs.onerrorOption.regex[oep]
  217. if regx != nil && regx != matchall {
  218. msg += regx.String() + "|" + msg
  219. }
  220. regx = regexp.MustCompile(msg)
  221. }
  222. ab.actionexprs.onerrorOption.regex[oep] = regx
  223. }
  224. }
  225. }
  226. return act
  227. }
  228. var ONERROR_ACTION_NAMES = strset.New("onerror", "noerrinfo")
  229. var STATIC_ACTION_NAMES = strset.New("skip", "retry", "scope", "beforerun", "set", "timeout", "qmeta", "loop", "loopfrom", "loopstep", "parallel", "fork", "wait", "sleep")
  230. var DYNAMIC_ACTION_NAMES = strset.New("subscribe", "unsubscribe", "params")
  231. var FOLLOWTHROUGH_ACTION_NAMES = strset.New("schema", "metainfo", "output", "outputcount", "count", "match", "matchcount", "equal")
  232. var time_layouts = []string{"2006-01-02 15:04:05", "2006-01-02", "2006-01-02 15:04:05.000", "2006-01-02 15:04:05.000000", "2006-01-02 15:04:05.000000000", "2006-01-02 15:04"}
  233. func ToStaticActions(actionexprs *ActionExprs) (staticActions *StaticActions, err error) {
  234. staticActions = actionexprs.staticActions
  235. if staticActions == nil {
  236. staticActions = &StaticActions{}
  237. actionexprs.staticActions = staticActions
  238. // skip 动作与位置顺序无关
  239. skip := actionexprs.Has("skip")
  240. actionexprs.Delete("skip")
  241. staticActions.Skip = skip
  242. if skip {
  243. // 跳过本条语句,不需要后续处理了
  244. return
  245. }
  246. // retry 动作与位置顺序无关
  247. retry_v, has_retry := actionexprs.Get("retry")
  248. actionexprs.Delete("retry")
  249. if has_retry {
  250. retry_args := retry_v.(*Action).Args
  251. retry_limit := 0
  252. if len(retry_args) > 0 {
  253. retry_limit = cast.ToInt(retry_args[0])
  254. if retry_limit < 0 {
  255. retry_limit = 0
  256. }
  257. }
  258. staticActions.RetryLimit = retry_limit
  259. }
  260. // scope 动作与位置顺序无关
  261. op_scope_v, has_scope := actionexprs.Get("scope")
  262. actionexprs.Delete("scope")
  263. if has_scope {
  264. op_scope_args := op_scope_v.(*Action).Args
  265. op_scope := "mql"
  266. if len(op_scope_args) > 0 {
  267. op_scope = cast.ToString(op_scope_args[0])
  268. if op_scope != "file" && op_scope != "dir" && op_scope != "top" {
  269. op_scope = "mql"
  270. }
  271. }
  272. staticActions.Scope = op_scope
  273. }
  274. // beforerun 动作与位置顺序无关
  275. op_beforerun_v, has_beforerun := actionexprs.Get("beforerun")
  276. actionexprs.Delete("beforerun")
  277. if has_beforerun {
  278. op_beforerun_args := op_beforerun_v.(*Action).Args
  279. for _, f := range op_beforerun_args {
  280. switch sf := f.(type) {
  281. case *Action:
  282. staticActions.BeforeRunActions = append(staticActions.BeforeRunActions, sf)
  283. }
  284. }
  285. }
  286. // set 动作与位置顺序无关
  287. op_set_v, has_set := actionexprs.Get("set")
  288. actionexprs.Delete("set")
  289. if has_set {
  290. op_set_args := op_set_v.(*Action).Args
  291. vars := map[string]interface{}{}
  292. for i := 0; i < len(op_set_args)-1; i += 2 {
  293. k := cast.ToString(op_set_args[i])
  294. v := op_set_args[i+1]
  295. switch av := v.(type) {
  296. case *qstru.Expr:
  297. ak := ""
  298. if len(av.VarName) > 0 {
  299. ak = av.VarName[0]
  300. }
  301. if ak == "now" {
  302. v = time.Now()
  303. }
  304. case string:
  305. for _, tf := range time_layouts {
  306. t, e := time.Parse(tf, av)
  307. if e == nil {
  308. v = t
  309. break
  310. }
  311. }
  312. }
  313. vars[k] = v
  314. }
  315. staticActions.Variables = vars
  316. }
  317. // timeout 动作与位置顺序无关
  318. op_timeout_v, has_timeout := actionexprs.Get("timeout")
  319. actionexprs.Delete("timeout")
  320. if has_timeout {
  321. op_timeout_args := op_timeout_v.(*Action).Args
  322. var op_timeout time.Duration
  323. if len(op_timeout_args) > 0 {
  324. op_timeout = mfmt.ParseDuration(strings.TrimSpace(cast.ToString(op_timeout_args[0])))
  325. }
  326. staticActions.Timeout = &op_timeout
  327. }
  328. // qmeta 动作与位置顺序无关
  329. op_qmeta_v, has_qmeta := actionexprs.Get("qmeta")
  330. actionexprs.Delete("qmeta")
  331. if has_qmeta {
  332. op_qmeta_args := op_qmeta_v.(*Action).Args
  333. var op_qmeta odb.QueryMeta
  334. if len(op_qmeta_args) > 0 {
  335. qm := odb.QueryMeta{}
  336. switch qmeta_arg := op_qmeta_args[0].(type) {
  337. case map[string]any:
  338. bs, e := json.Marshal(qmeta_arg)
  339. if e != nil {
  340. return nil, e
  341. }
  342. e = json.Unmarshal(bs, &qm)
  343. if e != nil {
  344. return nil, e
  345. }
  346. default:
  347. s := strings.TrimSpace(cast.ToString(op_qmeta_args[0]))
  348. e := json.Unmarshal([]byte(s), &qm)
  349. if e != nil {
  350. return nil, e
  351. }
  352. }
  353. op_qmeta = qm
  354. }
  355. staticActions.Qmeta = op_qmeta
  356. }
  357. // loop 动作与位置顺序无关
  358. op_loop_v, has_loop := actionexprs.Get("loop")
  359. actionexprs.Delete("loop")
  360. if has_loop {
  361. op_loop_args := op_loop_v.(*Action).Args
  362. if len(op_loop_args) > 0 {
  363. loopcount := cast.ToInt(op_loop_args[0])
  364. if loopcount == 0 {
  365. loopcount = 1
  366. } else if loopcount < 0 {
  367. loopcount = math.MaxInt
  368. }
  369. staticActions.LoopCount = &loopcount
  370. }
  371. }
  372. // loopfrom 动作与位置顺序无关
  373. op_loopfrom_v, has_loopfrom := actionexprs.Get("loopfrom")
  374. actionexprs.Delete("loopfrom")
  375. if has_loopfrom {
  376. op_loopfrom_args := op_loopfrom_v.(*Action).Args
  377. if len(op_loopfrom_args) > 0 {
  378. loopfrom := cast.ToInt(op_loopfrom_args[0])
  379. staticActions.LoopFrom = &loopfrom
  380. }
  381. }
  382. // loopstep 动作与位置顺序无关
  383. op_loopstep_v, has_loopstep := actionexprs.Get("loopstep")
  384. actionexprs.Delete("loopstep")
  385. if has_loopstep {
  386. op_loopstep_args := op_loopstep_v.(*Action).Args
  387. if len(op_loopstep_args) > 0 {
  388. loopstep := cast.ToInt(op_loopstep_args[0])
  389. staticActions.LoopStep = &loopstep
  390. }
  391. }
  392. // parallel 动作与位置顺序无关
  393. op_parallel_v, has_parallel := actionexprs.Get("parallel")
  394. actionexprs.Delete("parallel")
  395. if has_parallel {
  396. op_parallel_args := op_parallel_v.(*Action).Args
  397. parallelcount := 0
  398. if len(op_parallel_args) > 0 {
  399. parallelcount = cast.ToInt(op_parallel_args[0])
  400. }
  401. staticActions.ParallelCount = &parallelcount
  402. }
  403. // fork 动作与位置顺序无关
  404. op_fork_v, has_fork := actionexprs.Get("fork")
  405. actionexprs.Delete("fork")
  406. if has_fork {
  407. op_fork_args := op_fork_v.(*Action).Args
  408. fork_name := ""
  409. if len(op_fork_args) > 0 {
  410. fork_name = cast.ToString(op_fork_args[0])
  411. }
  412. staticActions.ForkName = &fork_name
  413. }
  414. // wait 动作与位置顺序无关
  415. op_wait_v, has_wait := actionexprs.Get("wait")
  416. actionexprs.Delete("wait")
  417. if has_wait {
  418. op_wait_args := op_wait_v.(*Action).Args
  419. wait_name := ""
  420. if len(op_wait_args) > 0 {
  421. wait_name = cast.ToString(op_wait_args[0])
  422. }
  423. staticActions.WaitName = &wait_name
  424. }
  425. // sleep 动作与位置顺序无关
  426. op_sleep_v, has_sleep := actionexprs.Get("sleep")
  427. actionexprs.Delete("sleep")
  428. if has_sleep {
  429. op_sleep_args := op_sleep_v.(*Action).Args
  430. var op_sleep_time time.Duration
  431. if len(op_sleep_args) > 0 {
  432. op_sleep_time = mfmt.ParseDuration(strings.TrimSpace(cast.ToString(op_sleep_args[0])))
  433. }
  434. staticActions.SleepTime = &op_sleep_time
  435. }
  436. }
  437. return
  438. }
  439. func (actionexprs *ActionExprs) DynamicActions() (dynamicActions *DynamicActions) {
  440. dynamicActions = actionexprs.dynamicActions
  441. if actionexprs.dynamicActions == nil {
  442. dynamicActions = &DynamicActions{}
  443. actionexprs.dynamicActions = dynamicActions
  444. // subscribe 动作与位置顺序无关
  445. op_subscribe_args := []string{}
  446. op_subscribe_v, has_subscribe := actionexprs.Get("subscribe")
  447. actionexprs.Delete("subscribe")
  448. if has_subscribe {
  449. args := op_subscribe_v.(*Action).Args
  450. for _, argv := range args {
  451. switch arg := argv.(type) {
  452. case map[string]interface{}:
  453. bs, e := json.Marshal(arg)
  454. if e == nil {
  455. op_subscribe_args = append(op_subscribe_args, string(bs))
  456. }
  457. default:
  458. op_subscribe_args = append(op_subscribe_args, cast.ToString(arg))
  459. }
  460. }
  461. if len(op_subscribe_args) > 0 {
  462. subscribe(op_subscribe_args...)
  463. }
  464. }
  465. dynamicActions.SubscribeArgs = op_subscribe_args
  466. // unsubscribe 动作与位置顺序无关
  467. op_unsubscribe_args := []string{}
  468. op_unsubscribe_v, has_unsubscribe := actionexprs.Get("unsubscribe")
  469. actionexprs.Delete("unsubscribe")
  470. if has_unsubscribe {
  471. op_unsubscribe_args = cast.ToStringSlice(op_unsubscribe_v.(*Action).Args)
  472. if len(op_unsubscribe_args) > 0 {
  473. unsubscribe(op_unsubscribe_args...)
  474. }
  475. }
  476. dynamicActions.UnsubscribeArgs = op_unsubscribe_args
  477. // params 动作与位置顺序无关
  478. op_params_str := ""
  479. op_params_v, has_params := actionexprs.Get("params")
  480. actionexprs.Delete("params")
  481. if has_params {
  482. op_params_args := op_params_v.(*Action).Args
  483. bs, e := json.Marshal(op_params_args)
  484. if e == nil {
  485. op_params_str = string(bs)
  486. } else {
  487. op_params_str = strings.TrimSpace(strings.Join(cast.ToStringSlice(op_params_args), ","))
  488. if len(op_params_str) == 0 || op_params_str[0] != '[' || op_params_str[len(op_params_str)-1] != ']' {
  489. op_params_str = "[" + op_params_str + "]"
  490. }
  491. }
  492. }
  493. dynamicActions.Params = op_params_str
  494. }
  495. return
  496. }
  497. // 其它后续动作
  498. func (actionexprs *ActionExprs) FollowThroughActions() []*Action {
  499. if actionexprs.followThroughActions == nil {
  500. actionexprs.Fetch(func(key, value interface{}) bool {
  501. name := key.(string)
  502. action := value.(*Action)
  503. if FOLLOWTHROUGH_ACTION_NAMES.Has(name) {
  504. actionexprs.followThroughActions = append(actionexprs.followThroughActions, action)
  505. }
  506. return true
  507. })
  508. }
  509. return actionexprs.followThroughActions
  510. }