feat:HAVING子句中支持CASE表达式

This commit is contained in:
rulego-team
2025-06-16 20:25:27 +08:00
parent 1500dc5d23
commit 89d0878913

View File

@ -409,6 +409,39 @@ func (s *Stream) process() {
// 应用 HAVING 过滤条件 // 应用 HAVING 过滤条件
if s.config.Having != "" { if s.config.Having != "" {
// 检查HAVING条件是否包含CASE表达式
hasCaseExpression := strings.Contains(strings.ToUpper(s.config.Having), "CASE")
var filteredResults []map[string]interface{}
if hasCaseExpression {
// HAVING条件包含CASE表达式使用我们的表达式解析器
expression, err := expr.NewExpression(s.config.Having)
if err != nil {
logger.Error("having filter error (CASE expression): %v", err)
} else {
// 应用 HAVING 过滤使用CASE表达式计算器
for _, result := range finalResults {
// 使用EvaluateWithNull方法以支持NULL值处理
havingResult, isNull, err := expression.EvaluateWithNull(result)
if err != nil {
logger.Error("having filter evaluation error: %v", err)
continue
}
// 如果结果是NULL则不满足条件SQL标准行为
if isNull {
continue
}
// 对于数值结果大于0视为true满足HAVING条件
if havingResult > 0 {
filteredResults = append(filteredResults, result)
}
}
}
} else {
// HAVING条件不包含CASE表达式使用原有的expr-lang处理
// 预处理HAVING条件中的LIKE语法转换为expr-lang可理解的形式 // 预处理HAVING条件中的LIKE语法转换为expr-lang可理解的形式
processedHaving := s.config.Having processedHaving := s.config.Having
bridge := functions.GetExprBridge() bridge := functions.GetExprBridge()
@ -431,16 +464,17 @@ func (s *Stream) process() {
logger.Error("having filter error: %v", err) logger.Error("having filter error: %v", err)
} else { } else {
// 应用 HAVING 过滤 // 应用 HAVING 过滤
var filteredResults []map[string]interface{}
for _, result := range finalResults { for _, result := range finalResults {
if havingFilter.Evaluate(result) { if havingFilter.Evaluate(result) {
filteredResults = append(filteredResults, result) filteredResults = append(filteredResults, result)
} }
} }
finalResults = filteredResults
} }
} }
finalResults = filteredResults
}
// 应用 LIMIT 限制 // 应用 LIMIT 限制
if s.config.Limit > 0 && len(finalResults) > s.config.Limit { if s.config.Limit > 0 && len(finalResults) > s.config.Limit {
finalResults = finalResults[:s.config.Limit] finalResults = finalResults[:s.config.Limit]