mirror of
https://gitee.com/rulego/streamsql.git
synced 2026-03-13 22:07:22 +00:00
246 lines
7.0 KiB
Go
246 lines
7.0 KiB
Go
package expr
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// parseCaseExpression parses CASE expression
|
|
func parseCaseExpression(tokens []string) (*ExprNode, []string, error) {
|
|
if len(tokens) == 0 || strings.ToUpper(tokens[0]) != "CASE" {
|
|
return nil, nil, fmt.Errorf("expected CASE keyword")
|
|
}
|
|
|
|
remaining := tokens[1:]
|
|
caseExpr := &CaseExpression{}
|
|
|
|
// Check if it's a simple CASE expression (CASE expr WHEN value THEN result)
|
|
if len(remaining) > 0 && strings.ToUpper(remaining[0]) != "WHEN" {
|
|
// Simple CASE expression
|
|
value, newRemaining, err := parseOrExpression(remaining)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error parsing CASE expression: %v", err)
|
|
}
|
|
caseExpr.Value = value
|
|
remaining = newRemaining
|
|
}
|
|
|
|
// Parse WHEN clauses
|
|
for len(remaining) > 0 && strings.ToUpper(remaining[0]) == "WHEN" {
|
|
remaining = remaining[1:] // Skip WHEN
|
|
|
|
// Parse WHEN condition
|
|
condition, newRemaining, err := parseOrExpression(remaining)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error parsing WHEN condition: %v", err)
|
|
}
|
|
remaining = newRemaining
|
|
|
|
// Check THEN keyword
|
|
if len(remaining) == 0 || strings.ToUpper(remaining[0]) != "THEN" {
|
|
return nil, nil, fmt.Errorf("expected THEN after WHEN condition")
|
|
}
|
|
remaining = remaining[1:] // Skip THEN
|
|
|
|
// Parse THEN result
|
|
result, newRemaining, err := parseOrExpression(remaining)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error parsing THEN result: %v", err)
|
|
}
|
|
remaining = newRemaining
|
|
|
|
// Add WHEN clause
|
|
caseExpr.WhenClauses = append(caseExpr.WhenClauses, WhenClause{
|
|
Condition: condition,
|
|
Result: result,
|
|
})
|
|
}
|
|
|
|
// Parse optional ELSE clause
|
|
if len(remaining) > 0 && strings.ToUpper(remaining[0]) == "ELSE" {
|
|
remaining = remaining[1:] // Skip ELSE
|
|
|
|
elseExpr, newRemaining, err := parseOrExpression(remaining)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error parsing ELSE expression: %v", err)
|
|
}
|
|
caseExpr.ElseResult = elseExpr
|
|
remaining = newRemaining
|
|
}
|
|
|
|
// Check END keyword
|
|
if len(remaining) == 0 || strings.ToUpper(remaining[0]) != "END" {
|
|
return nil, nil, fmt.Errorf("expected END to close CASE expression")
|
|
}
|
|
|
|
// Create ExprNode containing CaseExpression
|
|
caseNode := &ExprNode{
|
|
Type: TypeCase,
|
|
CaseExpr: caseExpr,
|
|
}
|
|
|
|
return caseNode, remaining[1:], nil
|
|
}
|
|
|
|
// evaluateCaseExpression evaluates the value of CASE expression
|
|
func evaluateCaseExpression(node *ExprNode, data map[string]interface{}) (float64, error) {
|
|
if node.Type != TypeCase {
|
|
return 0, fmt.Errorf("not a CASE expression")
|
|
}
|
|
|
|
if node.CaseExpr == nil {
|
|
return 0, fmt.Errorf("invalid CASE expression")
|
|
}
|
|
|
|
// Simple CASE expression: CASE expr WHEN value THEN result
|
|
if node.CaseExpr.Value != nil {
|
|
return evaluateSimpleCaseExpression(node, data)
|
|
}
|
|
|
|
// Search CASE expression: CASE WHEN condition THEN result
|
|
return evaluateSearchCaseExpression(node, data)
|
|
}
|
|
|
|
// evaluateSimpleCaseExpression evaluates simple CASE expression
|
|
func evaluateSimpleCaseExpression(node *ExprNode, data map[string]interface{}) (float64, error) {
|
|
caseExpr := node.CaseExpr
|
|
if caseExpr == nil {
|
|
return 0, fmt.Errorf("invalid CASE expression")
|
|
}
|
|
|
|
// Evaluate CASE expression value
|
|
caseValue, err := evaluateNodeValue(caseExpr.Value, data)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Iterate through WHEN clauses
|
|
for _, whenClause := range caseExpr.WhenClauses {
|
|
// Evaluate WHEN value
|
|
whenValue, err := evaluateNodeValue(whenClause.Condition, data)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Compare values
|
|
if compareValuesForEquality(caseValue, whenValue) {
|
|
// Evaluate and return THEN result
|
|
return evaluateNode(whenClause.Result, data)
|
|
}
|
|
}
|
|
|
|
// If no matching WHEN clause, evaluate ELSE expression
|
|
if caseExpr.ElseResult != nil {
|
|
return evaluateNode(caseExpr.ElseResult, data)
|
|
}
|
|
|
|
// If no ELSE clause, return NULL (return 0 here)
|
|
return 0, nil
|
|
}
|
|
|
|
// evaluateSearchCaseExpression evaluates search CASE expression
|
|
func evaluateSearchCaseExpression(node *ExprNode, data map[string]interface{}) (float64, error) {
|
|
caseExpr := node.CaseExpr
|
|
if caseExpr == nil {
|
|
return 0, fmt.Errorf("invalid CASE expression")
|
|
}
|
|
|
|
// Iterate through WHEN clauses
|
|
for _, whenClause := range caseExpr.WhenClauses {
|
|
// Evaluate WHEN condition - use boolean evaluation to handle logical operators
|
|
conditionResult, err := evaluateBoolNode(whenClause.Condition, data)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// If condition is true, return THEN result
|
|
if conditionResult {
|
|
return evaluateNode(whenClause.Result, data)
|
|
}
|
|
}
|
|
|
|
// If no matching WHEN clause, evaluate ELSE expression
|
|
if caseExpr.ElseResult != nil {
|
|
return evaluateNode(caseExpr.ElseResult, data)
|
|
}
|
|
|
|
// If no ELSE clause, return NULL (return 0 here)
|
|
return 0, nil
|
|
}
|
|
|
|
// evaluateCaseExpressionWithNull evaluates CASE expression with NULL value support
|
|
func evaluateCaseExpressionWithNull(node *ExprNode, data map[string]interface{}) (interface{}, bool, error) {
|
|
if node.Type != TypeCase {
|
|
return nil, false, fmt.Errorf("not a CASE expression")
|
|
}
|
|
|
|
caseExpr := node.CaseExpr
|
|
if caseExpr == nil {
|
|
return nil, false, fmt.Errorf("invalid CASE expression")
|
|
}
|
|
|
|
// Simple CASE expression: CASE expr WHEN value THEN result
|
|
if caseExpr.Value != nil {
|
|
return evaluateCaseExpressionValueWithNull(node, data)
|
|
}
|
|
|
|
// Search CASE expression: CASE WHEN condition THEN result
|
|
for _, whenClause := range caseExpr.WhenClauses {
|
|
// Evaluate WHEN condition - use boolean evaluation to handle logical operators
|
|
conditionResult, err := evaluateBoolNode(whenClause.Condition, data)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
// If condition is true, return THEN result
|
|
if conditionResult {
|
|
return evaluateNodeValueWithNull(whenClause.Result, data)
|
|
}
|
|
}
|
|
|
|
// If no matching WHEN clause, evaluate ELSE expression
|
|
if caseExpr.ElseResult != nil {
|
|
return evaluateNodeValueWithNull(caseExpr.ElseResult, data)
|
|
}
|
|
|
|
// If no ELSE clause, return NULL
|
|
return nil, true, nil
|
|
}
|
|
|
|
// evaluateCaseExpressionValueWithNull evaluates simple CASE expression (with NULL support)
|
|
func evaluateCaseExpressionValueWithNull(node *ExprNode, data map[string]interface{}) (interface{}, bool, error) {
|
|
caseExpr := node.CaseExpr
|
|
if caseExpr == nil {
|
|
return nil, false, fmt.Errorf("invalid CASE expression")
|
|
}
|
|
|
|
// Evaluate CASE expression value
|
|
caseValue, caseIsNull, err := evaluateNodeValueWithNull(caseExpr.Value, data)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
// Iterate through WHEN clauses
|
|
for _, whenClause := range caseExpr.WhenClauses {
|
|
// Evaluate WHEN value
|
|
whenValue, whenIsNull, err := evaluateNodeValueWithNull(whenClause.Condition, data)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
// Compare values (with NULL comparison support)
|
|
if compareValuesWithNullForEquality(caseValue, caseIsNull, whenValue, whenIsNull) {
|
|
// Evaluate and return THEN result
|
|
return evaluateNodeValueWithNull(whenClause.Result, data)
|
|
}
|
|
}
|
|
|
|
// If no matching WHEN clause, evaluate ELSE expression
|
|
if caseExpr.ElseResult != nil {
|
|
return evaluateNodeValueWithNull(caseExpr.ElseResult, data)
|
|
}
|
|
|
|
// If no ELSE clause, return NULL
|
|
return nil, true, nil
|
|
}
|