gitql_std/
window.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::collections::HashMap;
use std::sync::OnceLock;

use gitql_ast::types::any::AnyType;
use gitql_ast::types::dynamic::DynamicType;
use gitql_ast::types::integer::IntType;
use gitql_core::signature::Signature;
use gitql_core::signature::WindowFunction;
use gitql_core::values::base::Value;
use gitql_core::values::integer::IntValue;
use gitql_core::values::null::NullValue;

use crate::meta_types::first_element_type;

pub fn window_functions() -> &'static HashMap<&'static str, WindowFunction> {
    static HASHMAP: OnceLock<HashMap<&'static str, WindowFunction>> = OnceLock::new();
    HASHMAP.get_or_init(|| {
        let mut map: HashMap<&'static str, WindowFunction> = HashMap::new();
        map.insert("first_value", window_first_value);
        map.insert("nth_value", window_nth_value);
        map.insert("last_value", window_last_value);
        map.insert("row_number", window_row_number);
        map
    })
}

pub fn window_function_signatures() -> HashMap<&'static str, Signature> {
    let mut map: HashMap<&'static str, Signature> = HashMap::new();
    map.insert(
        "first_value",
        Signature {
            parameters: vec![Box::new(AnyType)],
            return_type: Box::new(DynamicType {
                function: first_element_type,
            }),
        },
    );

    map.insert(
        "nth_value",
        Signature {
            parameters: vec![Box::new(AnyType), Box::new(IntType)],
            return_type: Box::new(DynamicType {
                function: first_element_type,
            }),
        },
    );

    map.insert(
        "last_value",
        Signature {
            parameters: vec![Box::new(AnyType)],
            return_type: Box::new(DynamicType {
                function: first_element_type,
            }),
        },
    );

    map.insert(
        "row_number",
        Signature {
            parameters: vec![],
            return_type: Box::new(IntType),
        },
    );
    map
}

pub fn window_first_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
    let frame_len = frame.len();
    let first_value = &frame[0][0];
    let mut values = Vec::with_capacity(frame_len);
    for _ in 0..frame_len {
        values.push(first_value.clone());
    }
    values
}

pub fn window_nth_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
    let frame_len = frame.len();
    let index = frame[0][1].as_int().unwrap();

    let mut values: Vec<Box<dyn Value>> = Vec::with_capacity(frame_len);
    for _ in 0..frame_len {
        if index < 0 || index as usize >= frame_len {
            values.push(Box::new(NullValue));
        } else {
            values.push(frame[index as usize][0].clone());
        };
    }

    values
}

pub fn window_last_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
    let frame_len = frame.len();
    let last_value = &frame[frame_len - 1][0];
    let mut values = Vec::with_capacity(frame_len);
    for _ in 0..frame_len {
        values.push(last_value.clone());
    }
    values
}

pub fn window_row_number(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
    let frame_len = frame.len();
    let mut values: Vec<Box<dyn Value>> = Vec::with_capacity(frame_len);
    for i in 0..frame_len {
        let num = i as i64 + 1;
        values.push(Box::new(IntValue { value: num }));
    }
    values
}