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}