1use rudb_common::{Field, LogicalType};
29
30pub const DUCKDB: &str = "duckdb";
32
33#[must_use]
35pub fn database_fields() -> Vec<Field> {
36 vec![
37 Field::new("database_name", LogicalType::Varchar),
38 Field::new("database_oid", LogicalType::BigInt),
39 Field::new("path", LogicalType::Varchar),
40 Field::new("comment", LogicalType::Varchar),
41 Field::new("tags", tags()),
42 Field::new("internal", LogicalType::Boolean),
43 Field::new("type", LogicalType::Varchar),
44 Field::new("readonly", LogicalType::Boolean),
45 Field::new("encrypted", LogicalType::Boolean),
46 Field::new("cipher", LogicalType::Varchar),
47 Field::new("options", tags()),
48 ]
49}
50
51#[must_use]
57pub fn schema_fields() -> Vec<Field> {
58 vec![
59 Field::new("oid", LogicalType::BigInt),
60 Field::new("database_name", LogicalType::Varchar),
61 Field::new("database_oid", LogicalType::BigInt),
62 Field::new("schema_name", LogicalType::Varchar),
63 Field::new("comment", LogicalType::Varchar),
64 Field::new("tags", tags()),
65 Field::new("internal", LogicalType::Boolean),
66 Field::new("sql", LogicalType::Varchar),
67 Field::new("parent_schema", LogicalType::Varchar),
68 Field::new("parent_schema_oid", LogicalType::BigInt),
69 ]
70}
71
72#[must_use]
74pub fn table_fields() -> Vec<Field> {
75 vec![
76 Field::new("database_name", LogicalType::Varchar),
77 Field::new("database_oid", LogicalType::BigInt),
78 Field::new("schema_name", LogicalType::Varchar),
79 Field::new("schema_oid", LogicalType::BigInt),
80 Field::new("table_name", LogicalType::Varchar),
81 Field::new("table_oid", LogicalType::BigInt),
82 Field::new("comment", LogicalType::Varchar),
83 Field::new("tags", tags()),
84 Field::new("internal", LogicalType::Boolean),
85 Field::new("temporary", LogicalType::Boolean),
86 Field::new("has_primary_key", LogicalType::Boolean),
87 Field::new("estimated_size", LogicalType::BigInt),
88 Field::new("column_count", LogicalType::BigInt),
89 Field::new("index_count", LogicalType::BigInt),
90 Field::new("check_constraint_count", LogicalType::BigInt),
91 Field::new("sql", LogicalType::Varchar),
92 ]
93}
94
95#[must_use]
101pub fn view_fields() -> Vec<Field> {
102 vec![
103 Field::new("database_name", LogicalType::Varchar),
104 Field::new("database_oid", LogicalType::BigInt),
105 Field::new("schema_name", LogicalType::Varchar),
106 Field::new("schema_oid", LogicalType::BigInt),
107 Field::new("view_name", LogicalType::Varchar),
108 Field::new("view_oid", LogicalType::BigInt),
109 Field::new("comment", LogicalType::Varchar),
110 Field::new("tags", tags()),
111 Field::new("internal", LogicalType::Boolean),
112 Field::new("temporary", LogicalType::Boolean),
113 Field::new("column_count", LogicalType::BigInt),
114 Field::new("sql", LogicalType::Varchar),
115 Field::new("is_bound", LogicalType::Boolean),
116 ]
117}
118
119#[must_use]
124pub fn show_table_fields() -> Vec<Field> {
125 vec![Field::new("name", LogicalType::Varchar)]
126}
127
128#[must_use]
133pub fn show_database_fields() -> Vec<Field> {
134 vec![Field::new("database_name", LogicalType::Varchar)]
135}
136
137#[must_use]
143pub fn show_expanded_fields() -> Vec<Field> {
144 vec![
145 Field::new("database", LogicalType::Varchar),
146 Field::new("schema", LogicalType::Varchar),
147 Field::new("name", LogicalType::Varchar),
148 Field::new("column_names", LogicalType::list(LogicalType::Varchar)),
149 Field::new("column_types", LogicalType::list(LogicalType::Varchar)),
150 Field::new("temporary", LogicalType::Boolean),
151 ]
152}
153
154#[must_use]
156pub fn column_fields() -> Vec<Field> {
157 vec![
158 Field::new("database_name", LogicalType::Varchar),
159 Field::new("database_oid", LogicalType::BigInt),
160 Field::new("schema_name", LogicalType::Varchar),
161 Field::new("schema_oid", LogicalType::BigInt),
162 Field::new("table_name", LogicalType::Varchar),
163 Field::new("table_oid", LogicalType::BigInt),
164 Field::new("column_name", LogicalType::Varchar),
165 Field::new("column_index", LogicalType::Integer),
166 Field::new("comment", LogicalType::Varchar),
167 Field::new("internal", LogicalType::Boolean),
168 Field::new("column_default", LogicalType::Varchar),
169 Field::new("is_nullable", LogicalType::Boolean),
170 Field::new("data_type", LogicalType::Varchar),
171 Field::new("data_type_id", LogicalType::BigInt),
172 Field::new("character_maximum_length", LogicalType::Integer),
173 Field::new("numeric_precision", LogicalType::Integer),
174 Field::new("numeric_precision_radix", LogicalType::Integer),
175 Field::new("numeric_scale", LogicalType::Integer),
176 Field::new("tags", tags()),
177 Field::new("is_generated", LogicalType::Boolean),
178 Field::new("generation_expression", LogicalType::Varchar),
179 ]
180}
181
182#[must_use]
189pub fn canonical(ty: &LogicalType) -> String {
190 match ty {
191 LogicalType::Decimal { .. } => "DECIMAL".to_string(),
192 LogicalType::List(_) | LogicalType::Array(_, _) => "LIST".to_string(),
193 LogicalType::Map(_, _) => "MAP".to_string(),
194 LogicalType::Struct(_) => "STRUCT".to_string(),
195 LogicalType::Union(_) => "UNION".to_string(),
196 other => other.to_string(),
197 }
198}
199
200#[must_use]
210pub fn numeric_facts(ty: &LogicalType) -> (Option<i32>, Option<i32>, Option<i32>) {
211 let binary = |bits| (Some(bits), Some(2), Some(0));
212 match ty {
213 LogicalType::TinyInt => binary(8),
214 LogicalType::SmallInt => binary(16),
215 LogicalType::Integer => binary(32),
216 LogicalType::BigInt => binary(64),
217 LogicalType::HugeInt => binary(128),
218 LogicalType::Float => binary(24),
219 LogicalType::Double => binary(53),
220 LogicalType::Decimal { width, scale } => {
221 (Some(i32::from(*width)), Some(10), Some(i32::from(*scale)))
222 }
223 _ => (None, None, None),
224 }
225}
226
227fn tags() -> LogicalType {
229 LogicalType::map(LogicalType::Varchar, LogicalType::Varchar)
230}
231
232#[cfg(test)]
233mod tests {
234 use rudb_common::LogicalType;
235
236 use super::{
237 canonical, column_fields, database_fields, numeric_facts, schema_fields, table_fields,
238 view_fields,
239 };
240
241 #[test]
242 fn the_five_tables_are_the_shape_the_pin_returns() {
243 assert_eq!(database_fields().len(), 11);
244 assert_eq!(schema_fields().len(), 10);
245 assert_eq!(table_fields().len(), 16);
246 assert_eq!(view_fields().len(), 13);
247 assert_eq!(column_fields().len(), 21);
248 }
249
250 #[test]
252 fn a_numeric_precision_is_bits_everywhere_except_on_a_decimal() {
253 assert_eq!(numeric_facts(&LogicalType::Integer), (Some(32), Some(2), Some(0)));
254 assert_eq!(numeric_facts(&LogicalType::Double), (Some(53), Some(2), Some(0)));
255 assert_eq!(
256 numeric_facts(&LogicalType::Decimal { width: 9, scale: 2 }),
257 (Some(9), Some(10), Some(2))
258 );
259 assert_eq!(numeric_facts(&LogicalType::UBigInt), (None, None, None));
261 assert_eq!(numeric_facts(&LogicalType::Varchar), (None, None, None));
262 }
263
264 #[test]
265 fn a_types_modifiers_are_not_part_of_the_name_the_oid_is_keyed_by() {
266 assert_eq!(canonical(&LogicalType::Decimal { width: 9, scale: 2 }), "DECIMAL");
267 assert_eq!(canonical(&LogicalType::list(LogicalType::Integer)), "LIST");
268 assert_eq!(canonical(&LogicalType::Integer), "INTEGER");
269 assert_eq!(canonical(&LogicalType::TimestampTz), "TIMESTAMP WITH TIME ZONE");
270 }
271
272 #[test]
274 fn a_schemas_own_oid_is_spelled_oid_and_not_schema_oid() {
275 assert_eq!(schema_fields()[0].name, "oid");
276 assert!(schema_fields().iter().all(|field| field.name != "schema_oid"));
277 }
278}