checkAgg.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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 xsql
  15. import (
  16. "github.com/lf-edge/ekuiper/internal/binder/function"
  17. "github.com/lf-edge/ekuiper/pkg/ast"
  18. )
  19. // IsAggregate check if an expression is aggregate with the binding alias info
  20. func IsAggregate(expr ast.Expr) (r bool) {
  21. ast.WalkFunc(expr, func(n ast.Node) bool {
  22. switch f := n.(type) {
  23. case *ast.Call:
  24. if ok := function.IsAggFunc(f.Name); ok {
  25. r = true
  26. return false
  27. }
  28. case *ast.FieldRef:
  29. // lazy calculate
  30. if getOrCalculateAgg(f) {
  31. r = true
  32. return false
  33. }
  34. }
  35. return true
  36. })
  37. return
  38. }
  39. func getOrCalculateAgg(f *ast.FieldRef) bool {
  40. if f.IsAlias() {
  41. p := f.IsAggregate
  42. if p == nil {
  43. tr := IsAggregate(f.Expression)
  44. p = &tr
  45. f.IsAggregate = p
  46. }
  47. return *p
  48. }
  49. return false
  50. }
  51. func IsAggStatement(stmt *ast.SelectStatement) bool {
  52. if stmt.Dimensions != nil {
  53. ds := stmt.Dimensions.GetGroups()
  54. if ds != nil && len(ds) > 0 {
  55. return true
  56. }
  57. }
  58. r := false
  59. ast.WalkFunc(stmt.Fields, func(n ast.Node) bool {
  60. switch f := n.(type) {
  61. case *ast.Call:
  62. if ok := function.IsAggFunc(f.Name); ok {
  63. r = true
  64. return false
  65. }
  66. }
  67. return true
  68. })
  69. return r
  70. }
  71. func HasAggFuncs(node ast.Node) bool {
  72. if node == nil {
  73. return false
  74. }
  75. var r = false
  76. ast.WalkFunc(node, func(n ast.Node) bool {
  77. if f, ok := n.(*ast.Call); ok {
  78. if ok := function.IsAggFunc(f.Name); ok {
  79. r = true
  80. return false
  81. }
  82. }
  83. return true
  84. })
  85. return r
  86. }