datafusion_table_providers/util/
mod.rs1use snafu::prelude::*;
2use std::hash::Hash;
3
4use datafusion::common::DataFusionError;
5use std::collections::HashMap;
6
7use crate::UnsupportedTypeAction;
8
9pub mod column_reference;
10pub mod constraints;
11pub mod indexes;
12pub mod ns_lookup;
13pub mod on_conflict;
14pub mod retriable_error;
15
16#[cfg(any(feature = "sqlite", feature = "duckdb", feature = "postgres"))]
17pub mod schema;
18pub mod secrets;
19pub mod test;
20
21#[derive(Debug, Snafu)]
22pub enum Error {
23 #[snafu(display("Unable to generate SQL: {source}"))]
24 UnableToGenerateSQL {
25 source: datafusion::error::DataFusionError,
26 },
27}
28
29#[must_use]
30pub fn hashmap_from_option_string<K, V>(hashmap_option_str: &str) -> HashMap<K, V>
31where
32 K: for<'a> From<&'a str> + Eq + Hash,
33 V: for<'a> From<&'a str> + Default,
34{
35 hashmap_option_str
36 .split(';')
37 .map(|index| {
38 let parts: Vec<&str> = index.split(':').collect();
39 if parts.len() == 2 {
40 (K::from(parts[0]), V::from(parts[1]))
41 } else {
42 (K::from(index), V::default())
43 }
44 })
45 .collect()
46}
47
48#[must_use]
49pub fn remove_prefix_from_hashmap_keys<V>(
50 hashmap: HashMap<String, V>,
51 prefix: &str,
52) -> HashMap<String, V> {
53 hashmap
54 .into_iter()
55 .map(|(key, value)| {
56 let new_key = key
57 .strip_prefix(prefix)
58 .map_or(key.clone(), |s| s.to_string());
59 (new_key, value)
60 })
61 .collect()
62}
63
64#[must_use]
65pub fn to_datafusion_error<E>(error: E) -> DataFusionError
66where
67 E: std::error::Error + Send + Sync + 'static,
68{
69 DataFusionError::External(Box::new(error))
70}
71
72pub fn handle_unsupported_type_error<E>(
84 unsupported_type_action: UnsupportedTypeAction,
85 error: E,
86) -> Result<(), E>
87where
88 E: std::error::Error + Send + Sync,
89{
90 match unsupported_type_action {
91 UnsupportedTypeAction::Error | UnsupportedTypeAction::String => return Err(error),
92 UnsupportedTypeAction::Warn => {
93 tracing::warn!("{error}");
94 }
95 UnsupportedTypeAction::Ignore => {}
96 };
97
98 Ok(())
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use std::collections::HashMap;
105
106 #[test]
107 fn test_remove_prefix() {
108 let mut hashmap = HashMap::new();
109 hashmap.insert("prefix_key1".to_string(), "value1".to_string());
110 hashmap.insert("prefix_key2".to_string(), "value2".to_string());
111 hashmap.insert("key3".to_string(), "value3".to_string());
112
113 let result = remove_prefix_from_hashmap_keys(hashmap, "prefix_");
114
115 let mut expected = HashMap::new();
116 expected.insert("key1".to_string(), "value1".to_string());
117 expected.insert("key2".to_string(), "value2".to_string());
118 expected.insert("key3".to_string(), "value3".to_string());
119
120 assert_eq!(result, expected);
121 }
122
123 #[test]
124 fn test_no_prefix() {
125 let mut hashmap = HashMap::new();
126 hashmap.insert("key1".to_string(), "value1".to_string());
127 hashmap.insert("key2".to_string(), "value2".to_string());
128
129 let result = remove_prefix_from_hashmap_keys(hashmap, "prefix_");
130
131 let mut expected = HashMap::new();
132 expected.insert("key1".to_string(), "value1".to_string());
133 expected.insert("key2".to_string(), "value2".to_string());
134
135 assert_eq!(result, expected);
136 }
137
138 #[test]
139 fn test_empty_hashmap() {
140 let hashmap: HashMap<String, String> = HashMap::new();
141
142 let result = remove_prefix_from_hashmap_keys(hashmap, "prefix_");
143
144 let expected: HashMap<String, String> = HashMap::new();
145
146 assert_eq!(result, expected);
147 }
148
149 #[test]
150 fn test_full_prefix() {
151 let mut hashmap = HashMap::new();
152 hashmap.insert("prefix_".to_string(), "value1".to_string());
153 hashmap.insert("prefix_key2".to_string(), "value2".to_string());
154
155 let result = remove_prefix_from_hashmap_keys(hashmap, "prefix_");
156
157 let mut expected = HashMap::new();
158 expected.insert("".to_string(), "value1".to_string());
159 expected.insert("key2".to_string(), "value2".to_string());
160
161 assert_eq!(result, expected);
162 }
163}