aboutsummaryrefslogtreecommitdiff
path: root/weed/query/engine/data_conversion.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/query/engine/data_conversion.go')
-rw-r--r--weed/query/engine/data_conversion.go217
1 files changed, 217 insertions, 0 deletions
diff --git a/weed/query/engine/data_conversion.go b/weed/query/engine/data_conversion.go
new file mode 100644
index 000000000..f626d8f2e
--- /dev/null
+++ b/weed/query/engine/data_conversion.go
@@ -0,0 +1,217 @@
+package engine
+
+import (
+ "fmt"
+
+ "github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
+ "github.com/seaweedfs/seaweedfs/weed/query/sqltypes"
+)
+
+// formatAggregationResult formats an aggregation result into a SQL value
+func (e *SQLEngine) formatAggregationResult(spec AggregationSpec, result AggregationResult) sqltypes.Value {
+ switch spec.Function {
+ case "COUNT":
+ return sqltypes.NewInt64(result.Count)
+ case "SUM":
+ return sqltypes.NewFloat64(result.Sum)
+ case "AVG":
+ return sqltypes.NewFloat64(result.Sum) // Sum contains the average for AVG
+ case "MIN":
+ if result.Min != nil {
+ return e.convertRawValueToSQL(result.Min)
+ }
+ return sqltypes.NULL
+ case "MAX":
+ if result.Max != nil {
+ return e.convertRawValueToSQL(result.Max)
+ }
+ return sqltypes.NULL
+ }
+ return sqltypes.NULL
+}
+
+// convertRawValueToSQL converts a raw Go value to a SQL value
+func (e *SQLEngine) convertRawValueToSQL(value interface{}) sqltypes.Value {
+ switch v := value.(type) {
+ case int32:
+ return sqltypes.NewInt32(v)
+ case int64:
+ return sqltypes.NewInt64(v)
+ case float32:
+ return sqltypes.NewFloat32(v)
+ case float64:
+ return sqltypes.NewFloat64(v)
+ case string:
+ return sqltypes.NewVarChar(v)
+ case bool:
+ if v {
+ return sqltypes.NewVarChar("1")
+ }
+ return sqltypes.NewVarChar("0")
+ }
+ return sqltypes.NULL
+}
+
+// extractRawValue extracts the raw Go value from a schema_pb.Value
+func (e *SQLEngine) extractRawValue(value *schema_pb.Value) interface{} {
+ switch v := value.Kind.(type) {
+ case *schema_pb.Value_Int32Value:
+ return v.Int32Value
+ case *schema_pb.Value_Int64Value:
+ return v.Int64Value
+ case *schema_pb.Value_FloatValue:
+ return v.FloatValue
+ case *schema_pb.Value_DoubleValue:
+ return v.DoubleValue
+ case *schema_pb.Value_StringValue:
+ return v.StringValue
+ case *schema_pb.Value_BoolValue:
+ return v.BoolValue
+ case *schema_pb.Value_BytesValue:
+ return string(v.BytesValue) // Convert bytes to string for comparison
+ }
+ return nil
+}
+
+// compareValues compares two schema_pb.Value objects
+func (e *SQLEngine) compareValues(value1 *schema_pb.Value, value2 *schema_pb.Value) int {
+ if value2 == nil {
+ return 1 // value1 > nil
+ }
+ raw1 := e.extractRawValue(value1)
+ raw2 := e.extractRawValue(value2)
+ if raw1 == nil {
+ return -1
+ }
+ if raw2 == nil {
+ return 1
+ }
+
+ // Simple comparison - in a full implementation this would handle type coercion
+ switch v1 := raw1.(type) {
+ case int32:
+ if v2, ok := raw2.(int32); ok {
+ if v1 < v2 {
+ return -1
+ } else if v1 > v2 {
+ return 1
+ }
+ return 0
+ }
+ case int64:
+ if v2, ok := raw2.(int64); ok {
+ if v1 < v2 {
+ return -1
+ } else if v1 > v2 {
+ return 1
+ }
+ return 0
+ }
+ case float32:
+ if v2, ok := raw2.(float32); ok {
+ if v1 < v2 {
+ return -1
+ } else if v1 > v2 {
+ return 1
+ }
+ return 0
+ }
+ case float64:
+ if v2, ok := raw2.(float64); ok {
+ if v1 < v2 {
+ return -1
+ } else if v1 > v2 {
+ return 1
+ }
+ return 0
+ }
+ case string:
+ if v2, ok := raw2.(string); ok {
+ if v1 < v2 {
+ return -1
+ } else if v1 > v2 {
+ return 1
+ }
+ return 0
+ }
+ case bool:
+ if v2, ok := raw2.(bool); ok {
+ if v1 == v2 {
+ return 0
+ } else if v1 && !v2 {
+ return 1
+ }
+ return -1
+ }
+ }
+ return 0
+}
+
+// convertRawValueToSchemaValue converts raw Go values back to schema_pb.Value for comparison
+func (e *SQLEngine) convertRawValueToSchemaValue(rawValue interface{}) *schema_pb.Value {
+ switch v := rawValue.(type) {
+ case int32:
+ return &schema_pb.Value{Kind: &schema_pb.Value_Int32Value{Int32Value: v}}
+ case int64:
+ return &schema_pb.Value{Kind: &schema_pb.Value_Int64Value{Int64Value: v}}
+ case float32:
+ return &schema_pb.Value{Kind: &schema_pb.Value_FloatValue{FloatValue: v}}
+ case float64:
+ return &schema_pb.Value{Kind: &schema_pb.Value_DoubleValue{DoubleValue: v}}
+ case string:
+ return &schema_pb.Value{Kind: &schema_pb.Value_StringValue{StringValue: v}}
+ case bool:
+ return &schema_pb.Value{Kind: &schema_pb.Value_BoolValue{BoolValue: v}}
+ case []byte:
+ return &schema_pb.Value{Kind: &schema_pb.Value_BytesValue{BytesValue: v}}
+ default:
+ // Convert other types to string as fallback
+ return &schema_pb.Value{Kind: &schema_pb.Value_StringValue{StringValue: fmt.Sprintf("%v", v)}}
+ }
+}
+
+// convertJSONValueToSchemaValue converts JSON values to schema_pb.Value
+func (e *SQLEngine) convertJSONValueToSchemaValue(jsonValue interface{}) *schema_pb.Value {
+ switch v := jsonValue.(type) {
+ case string:
+ return &schema_pb.Value{Kind: &schema_pb.Value_StringValue{StringValue: v}}
+ case float64:
+ // JSON numbers are always float64, try to detect if it's actually an integer
+ if v == float64(int64(v)) {
+ return &schema_pb.Value{Kind: &schema_pb.Value_Int64Value{Int64Value: int64(v)}}
+ }
+ return &schema_pb.Value{Kind: &schema_pb.Value_DoubleValue{DoubleValue: v}}
+ case bool:
+ return &schema_pb.Value{Kind: &schema_pb.Value_BoolValue{BoolValue: v}}
+ case nil:
+ return nil
+ default:
+ // Convert other types to string
+ return &schema_pb.Value{Kind: &schema_pb.Value_StringValue{StringValue: fmt.Sprintf("%v", v)}}
+ }
+}
+
+// Helper functions for aggregation processing
+
+// isNullValue checks if a schema_pb.Value is null or empty
+func (e *SQLEngine) isNullValue(value *schema_pb.Value) bool {
+ return value == nil || value.Kind == nil
+}
+
+// convertToNumber converts a schema_pb.Value to a float64 for numeric operations
+func (e *SQLEngine) convertToNumber(value *schema_pb.Value) *float64 {
+ switch v := value.Kind.(type) {
+ case *schema_pb.Value_Int32Value:
+ result := float64(v.Int32Value)
+ return &result
+ case *schema_pb.Value_Int64Value:
+ result := float64(v.Int64Value)
+ return &result
+ case *schema_pb.Value_FloatValue:
+ result := float64(v.FloatValue)
+ return &result
+ case *schema_pb.Value_DoubleValue:
+ return &v.DoubleValue
+ }
+ return nil
+}