gitql_std/
window.rs

1use std::collections::HashMap;
2use std::sync::OnceLock;
3
4use gitql_ast::types::any::AnyType;
5use gitql_ast::types::dynamic::DynamicType;
6use gitql_ast::types::integer::IntType;
7use gitql_core::signature::Signature;
8use gitql_core::signature::WindowFunction;
9use gitql_core::values::integer::IntValue;
10use gitql_core::values::null::NullValue;
11use gitql_core::values::Value;
12
13use crate::meta_types::first_element_type;
14
15pub fn window_functions() -> &'static HashMap<&'static str, WindowFunction> {
16    static HASHMAP: OnceLock<HashMap<&'static str, WindowFunction>> = OnceLock::new();
17    HASHMAP.get_or_init(|| {
18        let mut map: HashMap<&'static str, WindowFunction> = HashMap::new();
19        map.insert("first_value", window_first_value);
20        map.insert("nth_value", window_nth_value);
21        map.insert("last_value", window_last_value);
22        map.insert("row_number", window_row_number);
23        map
24    })
25}
26
27pub fn window_function_signatures() -> HashMap<&'static str, Signature> {
28    let mut map: HashMap<&'static str, Signature> = HashMap::new();
29    map.insert(
30        "first_value",
31        Signature {
32            parameters: vec![Box::new(AnyType)],
33            return_type: Box::new(DynamicType {
34                function: first_element_type,
35            }),
36        },
37    );
38
39    map.insert(
40        "nth_value",
41        Signature {
42            parameters: vec![Box::new(AnyType), Box::new(IntType)],
43            return_type: Box::new(DynamicType {
44                function: first_element_type,
45            }),
46        },
47    );
48
49    map.insert(
50        "last_value",
51        Signature {
52            parameters: vec![Box::new(AnyType)],
53            return_type: Box::new(DynamicType {
54                function: first_element_type,
55            }),
56        },
57    );
58
59    map.insert(
60        "row_number",
61        Signature {
62            parameters: vec![],
63            return_type: Box::new(IntType),
64        },
65    );
66    map
67}
68
69pub fn window_first_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
70    let frame_len = frame.len();
71    let first_value = &frame[0][0];
72    let mut values = Vec::with_capacity(frame_len);
73    for _ in 0..frame_len {
74        values.push(first_value.clone());
75    }
76    values
77}
78
79pub fn window_nth_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
80    let frame_len = frame.len();
81    let index = frame[0][1].as_int().unwrap();
82
83    let mut values: Vec<Box<dyn Value>> = Vec::with_capacity(frame_len);
84    for _ in 0..frame_len {
85        if index < 0 || index as usize >= frame_len {
86            values.push(Box::new(NullValue));
87        } else {
88            values.push(frame[index as usize][0].clone());
89        };
90    }
91
92    values
93}
94
95pub fn window_last_value(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
96    let frame_len = frame.len();
97    let last_value = &frame[frame_len - 1][0];
98    let mut values = Vec::with_capacity(frame_len);
99    for _ in 0..frame_len {
100        values.push(last_value.clone());
101    }
102    values
103}
104
105pub fn window_row_number(frame: &[Vec<Box<dyn Value>>]) -> Vec<Box<dyn Value>> {
106    let frame_len = frame.len();
107    let mut values: Vec<Box<dyn Value>> = Vec::with_capacity(frame_len);
108    for i in 0..frame_len {
109        let num = i as i64 + 1;
110        values.push(Box::new(IntValue { value: num }));
111    }
112    values
113}