iceberg_rust_spec/spec/
sort.rs1use std::{fmt, str};
17
18use derive_builder::Builder;
19use serde::{Deserialize, Serialize};
20
21use crate::error::Error;
22
23use super::partition::Transform;
24
25pub static DEFAULT_SORT_ORDER_ID: i32 = 0;
26
27#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
28pub enum SortDirection {
30 #[serde(rename = "asc")]
32 Ascending,
33 #[serde(rename = "desc")]
35 Descending,
36}
37
38#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
39pub enum NullOrder {
41 #[serde(rename = "nulls-first")]
42 First,
44 #[serde(rename = "nulls-last")]
45 Last,
47}
48
49#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
50#[serde(rename_all = "kebab-case")]
51pub struct SortField {
53 pub source_id: i32,
55 pub transform: Transform,
57 pub direction: SortDirection,
59 pub null_order: NullOrder,
61}
62
63#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default, Builder)]
64#[serde(rename_all = "kebab-case")]
65#[builder(setter(prefix = "with"))]
66pub struct SortOrder {
69 #[builder(default = "DEFAULT_SORT_ORDER_ID")]
71 pub order_id: i32,
72 #[builder(setter(each(name = "with_sort_field")))]
73 pub fields: Vec<SortField>,
75}
76
77impl fmt::Display for SortOrder {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(
80 f,
81 "{}",
82 &serde_json::to_string(self).map_err(|_| fmt::Error)?,
83 )
84 }
85}
86
87impl str::FromStr for SortOrder {
88 type Err = Error;
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
90 serde_json::from_str(s).map_err(Error::from)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn sort_field() {
100 let sort_field = r#"
101 {
102 "transform": "bucket[4]",
103 "source-id": 3,
104 "direction": "desc",
105 "null-order": "nulls-last"
106 }
107 "#;
108
109 let field: SortField = serde_json::from_str(sort_field).unwrap();
110 assert_eq!(Transform::Bucket(4), field.transform);
111 assert_eq!(3, field.source_id);
112 assert_eq!(SortDirection::Descending, field.direction);
113 assert_eq!(NullOrder::Last, field.null_order);
114 }
115
116 #[test]
117 fn sort_order() {
118 let sort_order = r#"
119 {
120 "order-id": 1,
121 "fields": [ {
122 "transform": "identity",
123 "source-id": 2,
124 "direction": "asc",
125 "null-order": "nulls-first"
126 }, {
127 "transform": "bucket[4]",
128 "source-id": 3,
129 "direction": "desc",
130 "null-order": "nulls-last"
131 } ]
132 }
133 "#;
134
135 let order: SortOrder = serde_json::from_str(sort_order).unwrap();
136 assert_eq!(Transform::Identity, order.fields[0].transform);
137 assert_eq!(2, order.fields[0].source_id);
138 assert_eq!(SortDirection::Ascending, order.fields[0].direction);
139 assert_eq!(NullOrder::First, order.fields[0].null_order);
140
141 assert_eq!(Transform::Bucket(4), order.fields[1].transform);
142 assert_eq!(3, order.fields[1].source_id);
143 assert_eq!(SortDirection::Descending, order.fields[1].direction);
144 assert_eq!(NullOrder::Last, order.fields[1].null_order);
145 }
146}