You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.9 KiB
90 lines
2.9 KiB
package engine
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/schema_pb"
|
|
)
|
|
|
|
// WindowFunctionDemo demonstrates basic window function concepts for timestamp-based analytics
|
|
// This provides a foundation for full window function implementation
|
|
|
|
// ApplyRowNumber applies ROW_NUMBER() OVER (ORDER BY timestamp) to a result set
|
|
func (e *SQLEngine) ApplyRowNumber(results []HybridScanResult, orderByColumn string) []HybridScanResult {
|
|
// Sort results by timestamp if ordering by timestamp-related fields
|
|
if orderByColumn == "timestamp" || orderByColumn == "_timestamp_ns" {
|
|
sort.Slice(results, func(i, j int) bool {
|
|
return results[i].Timestamp < results[j].Timestamp
|
|
})
|
|
}
|
|
|
|
// Add ROW_NUMBER as a synthetic column
|
|
for i := range results {
|
|
if results[i].Values == nil {
|
|
results[i].Values = make(map[string]*schema_pb.Value)
|
|
}
|
|
results[i].Values["row_number"] = &schema_pb.Value{
|
|
Kind: &schema_pb.Value_Int64Value{Int64Value: int64(i + 1)},
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// ExtractYear extracts the year from a TIMESTAMP logical type
|
|
func (e *SQLEngine) ExtractYear(timestampValue *schema_pb.TimestampValue) int {
|
|
if timestampValue == nil {
|
|
return 0
|
|
}
|
|
|
|
// Convert microseconds to seconds and create time
|
|
t := time.Unix(timestampValue.TimestampMicros/1_000_000, 0)
|
|
return t.Year()
|
|
}
|
|
|
|
// ExtractMonth extracts the month from a TIMESTAMP logical type
|
|
func (e *SQLEngine) ExtractMonth(timestampValue *schema_pb.TimestampValue) int {
|
|
if timestampValue == nil {
|
|
return 0
|
|
}
|
|
|
|
t := time.Unix(timestampValue.TimestampMicros/1_000_000, 0)
|
|
return int(t.Month())
|
|
}
|
|
|
|
// ExtractDay extracts the day from a TIMESTAMP logical type
|
|
func (e *SQLEngine) ExtractDay(timestampValue *schema_pb.TimestampValue) int {
|
|
if timestampValue == nil {
|
|
return 0
|
|
}
|
|
|
|
t := time.Unix(timestampValue.TimestampMicros/1_000_000, 0)
|
|
return t.Day()
|
|
}
|
|
|
|
// FilterByYear demonstrates filtering TIMESTAMP values by year
|
|
func (e *SQLEngine) FilterByYear(results []HybridScanResult, targetYear int) []HybridScanResult {
|
|
var filtered []HybridScanResult
|
|
|
|
for _, result := range results {
|
|
if timestampField := result.Values["timestamp"]; timestampField != nil {
|
|
if timestampVal, ok := timestampField.Kind.(*schema_pb.Value_TimestampValue); ok {
|
|
year := e.ExtractYear(timestampVal.TimestampValue)
|
|
if year == targetYear {
|
|
filtered = append(filtered, result)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return filtered
|
|
}
|
|
|
|
// This demonstrates the foundation for more complex window functions like:
|
|
// - LAG(value, offset) OVER (ORDER BY timestamp) - Access previous row value
|
|
// - LEAD(value, offset) OVER (ORDER BY timestamp) - Access next row value
|
|
// - RANK() OVER (ORDER BY timestamp) - Ranking with gaps for ties
|
|
// - DENSE_RANK() OVER (ORDER BY timestamp) - Ranking without gaps
|
|
// - FIRST_VALUE(value) OVER (PARTITION BY category ORDER BY timestamp) - First value in window
|
|
// - LAST_VALUE(value) OVER (PARTITION BY category ORDER BY timestamp) - Last value in window
|