arithmetic_functions.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package engine
  2. import (
  3. "fmt"
  4. "math"
  5. "github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
  6. )
  7. // ===============================
  8. // ARITHMETIC OPERATORS
  9. // ===============================
  10. // ArithmeticOperator represents basic arithmetic operations
  11. type ArithmeticOperator string
  12. const (
  13. OpAdd ArithmeticOperator = "+"
  14. OpSub ArithmeticOperator = "-"
  15. OpMul ArithmeticOperator = "*"
  16. OpDiv ArithmeticOperator = "/"
  17. OpMod ArithmeticOperator = "%"
  18. )
  19. // EvaluateArithmeticExpression evaluates basic arithmetic operations between two values
  20. func (e *SQLEngine) EvaluateArithmeticExpression(left, right *schema_pb.Value, operator ArithmeticOperator) (*schema_pb.Value, error) {
  21. if left == nil || right == nil {
  22. return nil, fmt.Errorf("arithmetic operation requires non-null operands")
  23. }
  24. // Convert values to numeric types for calculation
  25. leftNum, err := e.valueToFloat64(left)
  26. if err != nil {
  27. return nil, fmt.Errorf("left operand conversion error: %v", err)
  28. }
  29. rightNum, err := e.valueToFloat64(right)
  30. if err != nil {
  31. return nil, fmt.Errorf("right operand conversion error: %v", err)
  32. }
  33. var result float64
  34. var resultErr error
  35. switch operator {
  36. case OpAdd:
  37. result = leftNum + rightNum
  38. case OpSub:
  39. result = leftNum - rightNum
  40. case OpMul:
  41. result = leftNum * rightNum
  42. case OpDiv:
  43. if rightNum == 0 {
  44. return nil, fmt.Errorf("division by zero")
  45. }
  46. result = leftNum / rightNum
  47. case OpMod:
  48. if rightNum == 0 {
  49. return nil, fmt.Errorf("modulo by zero")
  50. }
  51. result = math.Mod(leftNum, rightNum)
  52. default:
  53. return nil, fmt.Errorf("unsupported arithmetic operator: %s", operator)
  54. }
  55. if resultErr != nil {
  56. return nil, resultErr
  57. }
  58. // Convert result back to appropriate schema value type
  59. // If both operands were integers and operation doesn't produce decimal, return integer
  60. if e.isIntegerValue(left) && e.isIntegerValue(right) &&
  61. (operator == OpAdd || operator == OpSub || operator == OpMul || operator == OpMod) {
  62. return &schema_pb.Value{
  63. Kind: &schema_pb.Value_Int64Value{Int64Value: int64(result)},
  64. }, nil
  65. }
  66. // Otherwise return as double/float
  67. return &schema_pb.Value{
  68. Kind: &schema_pb.Value_DoubleValue{DoubleValue: result},
  69. }, nil
  70. }
  71. // Add evaluates addition (left + right)
  72. func (e *SQLEngine) Add(left, right *schema_pb.Value) (*schema_pb.Value, error) {
  73. return e.EvaluateArithmeticExpression(left, right, OpAdd)
  74. }
  75. // Subtract evaluates subtraction (left - right)
  76. func (e *SQLEngine) Subtract(left, right *schema_pb.Value) (*schema_pb.Value, error) {
  77. return e.EvaluateArithmeticExpression(left, right, OpSub)
  78. }
  79. // Multiply evaluates multiplication (left * right)
  80. func (e *SQLEngine) Multiply(left, right *schema_pb.Value) (*schema_pb.Value, error) {
  81. return e.EvaluateArithmeticExpression(left, right, OpMul)
  82. }
  83. // Divide evaluates division (left / right)
  84. func (e *SQLEngine) Divide(left, right *schema_pb.Value) (*schema_pb.Value, error) {
  85. return e.EvaluateArithmeticExpression(left, right, OpDiv)
  86. }
  87. // Modulo evaluates modulo operation (left % right)
  88. func (e *SQLEngine) Modulo(left, right *schema_pb.Value) (*schema_pb.Value, error) {
  89. return e.EvaluateArithmeticExpression(left, right, OpMod)
  90. }
  91. // ===============================
  92. // MATHEMATICAL FUNCTIONS
  93. // ===============================
  94. // Round rounds a numeric value to the nearest integer or specified decimal places
  95. func (e *SQLEngine) Round(value *schema_pb.Value, precision ...*schema_pb.Value) (*schema_pb.Value, error) {
  96. if value == nil {
  97. return nil, fmt.Errorf("ROUND function requires non-null value")
  98. }
  99. num, err := e.valueToFloat64(value)
  100. if err != nil {
  101. return nil, fmt.Errorf("ROUND function conversion error: %v", err)
  102. }
  103. // Default precision is 0 (round to integer)
  104. precisionValue := 0
  105. if len(precision) > 0 && precision[0] != nil {
  106. precFloat, err := e.valueToFloat64(precision[0])
  107. if err != nil {
  108. return nil, fmt.Errorf("ROUND precision conversion error: %v", err)
  109. }
  110. precisionValue = int(precFloat)
  111. }
  112. // Apply rounding
  113. multiplier := math.Pow(10, float64(precisionValue))
  114. rounded := math.Round(num*multiplier) / multiplier
  115. // Return as integer if precision is 0 and original was integer, otherwise as double
  116. if precisionValue == 0 && e.isIntegerValue(value) {
  117. return &schema_pb.Value{
  118. Kind: &schema_pb.Value_Int64Value{Int64Value: int64(rounded)},
  119. }, nil
  120. }
  121. return &schema_pb.Value{
  122. Kind: &schema_pb.Value_DoubleValue{DoubleValue: rounded},
  123. }, nil
  124. }
  125. // Ceil returns the smallest integer greater than or equal to the value
  126. func (e *SQLEngine) Ceil(value *schema_pb.Value) (*schema_pb.Value, error) {
  127. if value == nil {
  128. return nil, fmt.Errorf("CEIL function requires non-null value")
  129. }
  130. num, err := e.valueToFloat64(value)
  131. if err != nil {
  132. return nil, fmt.Errorf("CEIL function conversion error: %v", err)
  133. }
  134. result := math.Ceil(num)
  135. return &schema_pb.Value{
  136. Kind: &schema_pb.Value_Int64Value{Int64Value: int64(result)},
  137. }, nil
  138. }
  139. // Floor returns the largest integer less than or equal to the value
  140. func (e *SQLEngine) Floor(value *schema_pb.Value) (*schema_pb.Value, error) {
  141. if value == nil {
  142. return nil, fmt.Errorf("FLOOR function requires non-null value")
  143. }
  144. num, err := e.valueToFloat64(value)
  145. if err != nil {
  146. return nil, fmt.Errorf("FLOOR function conversion error: %v", err)
  147. }
  148. result := math.Floor(num)
  149. return &schema_pb.Value{
  150. Kind: &schema_pb.Value_Int64Value{Int64Value: int64(result)},
  151. }, nil
  152. }
  153. // Abs returns the absolute value of a number
  154. func (e *SQLEngine) Abs(value *schema_pb.Value) (*schema_pb.Value, error) {
  155. if value == nil {
  156. return nil, fmt.Errorf("ABS function requires non-null value")
  157. }
  158. num, err := e.valueToFloat64(value)
  159. if err != nil {
  160. return nil, fmt.Errorf("ABS function conversion error: %v", err)
  161. }
  162. result := math.Abs(num)
  163. // Return same type as input if possible
  164. if e.isIntegerValue(value) {
  165. return &schema_pb.Value{
  166. Kind: &schema_pb.Value_Int64Value{Int64Value: int64(result)},
  167. }, nil
  168. }
  169. // Check if original was float32
  170. if _, ok := value.Kind.(*schema_pb.Value_FloatValue); ok {
  171. return &schema_pb.Value{
  172. Kind: &schema_pb.Value_FloatValue{FloatValue: float32(result)},
  173. }, nil
  174. }
  175. // Default to double
  176. return &schema_pb.Value{
  177. Kind: &schema_pb.Value_DoubleValue{DoubleValue: result},
  178. }, nil
  179. }