Browse Source

fix empty spaces and coercion

pull/7185/head
chrislu 1 month ago
parent
commit
59d6806146
  1. 4
      SQL_FEATURE_PLAN.md
  2. 119
      weed/query/engine/engine.go

4
SQL_FEATURE_PLAN.md

@ -16,7 +16,7 @@ To provide a full-featured SQL interface for SeaweedFS, treating schema-tized MQ
* **Schema-tized Topic Management (Priority 1):** * **Schema-tized Topic Management (Priority 1):**
* `SHOW DATABASES` - List all MQ namespaces * `SHOW DATABASES` - List all MQ namespaces
* `SHOW TABLES` - List all topics in a namespace
* `SHOW TABLES` - List all topics in a namespace
* `CREATE TABLE topic_name (field1 INT, field2 STRING, ...)` - Create new MQ topic with schema * `CREATE TABLE topic_name (field1 INT, field2 STRING, ...)` - Create new MQ topic with schema
* `ALTER TABLE topic_name ADD COLUMN field3 BOOL` - Modify topic schema (with versioning) * `ALTER TABLE topic_name ADD COLUMN field3 BOOL` - Modify topic schema (with versioning)
* `DROP TABLE topic_name` - Delete MQ topic * `DROP TABLE topic_name` - Delete MQ topic
@ -202,7 +202,7 @@ SQL Query Flow:
**1. SQL-to-MQ Mapping Strategy:** **1. SQL-to-MQ Mapping Strategy:**
* MQ Namespaces ↔ SQL Databases * MQ Namespaces ↔ SQL Databases
* MQ Topics ↔ SQL Tables
* MQ Topics ↔ SQL Tables
* Topic Partitions ↔ Table Shards (transparent to users) * Topic Partitions ↔ Table Shards (transparent to users)
* Schema Fields ↔ Table Columns * Schema Fields ↔ Table Columns

119
weed/query/engine/engine.go

@ -1383,65 +1383,98 @@ func (e *SQLEngine) evaluateComparison(fieldValue *schema_pb.Value, operator str
} }
} }
// Helper functions for value comparison (simplified implementation)
// Helper functions for value comparison with proper type coercion
func (e *SQLEngine) valuesEqual(fieldValue *schema_pb.Value, compareValue interface{}) bool { func (e *SQLEngine) valuesEqual(fieldValue *schema_pb.Value, compareValue interface{}) bool {
switch v := fieldValue.Kind.(type) {
case *schema_pb.Value_Int32Value:
if intVal, ok := compareValue.(int64); ok {
if intVal > math.MaxInt32 || intVal < math.MinInt32 {
return false // Value out of range for int32, cannot be equal
}
return v.Int32Value == int32(intVal)
}
case *schema_pb.Value_Int64Value:
if intVal, ok := compareValue.(int64); ok {
return v.Int64Value == intVal
}
case *schema_pb.Value_StringValue:
// Handle string comparisons first
if strField, ok := fieldValue.Kind.(*schema_pb.Value_StringValue); ok {
if strVal, ok := compareValue.(string); ok { if strVal, ok := compareValue.(string); ok {
return v.StringValue == strVal
return strField.StringValue == strVal
}
return false
}
// Handle boolean comparisons
if boolField, ok := fieldValue.Kind.(*schema_pb.Value_BoolValue); ok {
if boolVal, ok := compareValue.(bool); ok {
return boolField.BoolValue == boolVal
} }
return false
} }
// Handle numeric comparisons with type coercion
fieldNum := e.convertToNumber(fieldValue)
compareNum := e.convertCompareValueToNumber(compareValue)
if fieldNum != nil && compareNum != nil {
return *fieldNum == *compareNum
}
return false return false
} }
func (e *SQLEngine) valueLessThan(fieldValue *schema_pb.Value, compareValue interface{}) bool {
switch v := fieldValue.Kind.(type) {
case *schema_pb.Value_Int32Value:
if intVal, ok := compareValue.(int64); ok {
if intVal > math.MaxInt32 {
return true // int32 value is always less than values > MaxInt32
}
if intVal < math.MinInt32 {
return false // int32 value is always greater than values < MinInt32
}
return v.Int32Value < int32(intVal)
// convertCompareValueToNumber converts compare values from SQL queries to float64
func (e *SQLEngine) convertCompareValueToNumber(compareValue interface{}) *float64 {
switch v := compareValue.(type) {
case int:
result := float64(v)
return &result
case int32:
result := float64(v)
return &result
case int64:
result := float64(v)
return &result
case float32:
result := float64(v)
return &result
case float64:
return &v
case string:
// Try to parse string as number for flexible comparisons
if parsed, err := strconv.ParseFloat(v, 64); err == nil {
return &parsed
} }
case *schema_pb.Value_Int64Value:
if intVal, ok := compareValue.(int64); ok {
return v.Int64Value < intVal
}
return nil
}
func (e *SQLEngine) valueLessThan(fieldValue *schema_pb.Value, compareValue interface{}) bool {
// Handle string comparisons lexicographically
if strField, ok := fieldValue.Kind.(*schema_pb.Value_StringValue); ok {
if strVal, ok := compareValue.(string); ok {
return strField.StringValue < strVal
} }
return false
}
// Handle numeric comparisons with type coercion
fieldNum := e.convertToNumber(fieldValue)
compareNum := e.convertCompareValueToNumber(compareValue)
if fieldNum != nil && compareNum != nil {
return *fieldNum < *compareNum
} }
return false return false
} }
func (e *SQLEngine) valueGreaterThan(fieldValue *schema_pb.Value, compareValue interface{}) bool { func (e *SQLEngine) valueGreaterThan(fieldValue *schema_pb.Value, compareValue interface{}) bool {
switch v := fieldValue.Kind.(type) {
case *schema_pb.Value_Int32Value:
if intVal, ok := compareValue.(int64); ok {
if intVal > math.MaxInt32 {
return false // int32 value is never greater than values > MaxInt32
}
if intVal < math.MinInt32 {
return true // int32 value is always greater than values < MinInt32
}
return v.Int32Value > int32(intVal)
}
case *schema_pb.Value_Int64Value:
if intVal, ok := compareValue.(int64); ok {
return v.Int64Value > intVal
// Handle string comparisons lexicographically
if strField, ok := fieldValue.Kind.(*schema_pb.Value_StringValue); ok {
if strVal, ok := compareValue.(string); ok {
return strField.StringValue > strVal
} }
return false
}
// Handle numeric comparisons with type coercion
fieldNum := e.convertToNumber(fieldValue)
compareNum := e.convertCompareValueToNumber(compareValue)
if fieldNum != nil && compareNum != nil {
return *fieldNum > *compareNum
} }
return false return false
} }

Loading…
Cancel
Save