1use crate::prelude::*;
2use crate::{ToSQL, sql::SQL, traits::SQLParam};
3use core::any::Any;
4
5#[cfg(feature = "std")]
6use std::collections::BTreeSet;
7
8pub trait SQLEnumInfo: Any + Send + Sync {
10 fn name(&self) -> &'static str;
12
13 fn create_type_sql(&self) -> String;
15
16 fn variants(&self) -> &'static [&'static str];
18}
19
20impl core::fmt::Debug for dyn SQLEnumInfo {
21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22 f.debug_struct("SQLEnumInfo")
23 .field("name", &self.name())
24 .field("variants", &self.variants())
25 .finish()
26 }
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31pub enum OrderBy {
32 Asc,
33 Desc,
34}
35
36pub fn asc<'a, V, T>(column: T) -> SQL<'a, V>
38where
39 V: SQLParam + 'a,
40 T: ToSQL<'a, V>,
41{
42 column.to_sql().append(&OrderBy::Asc)
43}
44
45pub fn desc<'a, V, T>(column: T) -> SQL<'a, V>
47where
48 V: SQLParam + 'a,
49 T: ToSQL<'a, V>,
50{
51 column.to_sql().append(&OrderBy::Desc)
52}
53
54#[cfg(feature = "std")]
63#[allow(dead_code)]
64pub(crate) fn topological_order<'a>(
65 items: impl IntoIterator<Item = (&'a str, &'a [&'a str])>,
66) -> crate::error::Result<Vec<&'a str>> {
67 let items: Vec<_> = items.into_iter().collect();
68 let name_set: HashMap<&str, usize> = items
69 .iter()
70 .enumerate()
71 .map(|(i, (name, _))| (*name, i))
72 .collect();
73
74 let n = items.len();
75 let mut indegree = vec![0usize; n];
76 let mut reverse_edges: Vec<Vec<usize>> = vec![Vec::new(); n];
77
78 for (i, (_name, deps)) in items.iter().enumerate() {
79 for dep in *deps {
80 if let Some(&j) = name_set.get(dep) {
81 indegree[i] += 1;
82 reverse_edges[j].push(i);
83 }
84 }
85 }
86
87 let mut queue: BTreeSet<(&str, usize)> = BTreeSet::new();
88 for (i, °) in indegree.iter().enumerate() {
89 if deg == 0 {
90 queue.insert((items[i].0, i));
91 }
92 }
93
94 let mut result = Vec::with_capacity(n);
95 while let Some(&entry) = queue.first() {
96 queue.remove(&entry);
97 let (_name, idx) = entry;
98 result.push(items[idx].0);
99
100 for &neighbor in &reverse_edges[idx] {
101 indegree[neighbor] -= 1;
102 if indegree[neighbor] == 0 {
103 queue.insert((items[neighbor].0, neighbor));
104 }
105 }
106 }
107
108 if result.len() != n {
109 return Err(crate::error::DrizzleError::Schema(
110 "cycle detected in table dependencies".into(),
111 ));
112 }
113
114 Ok(result)
115}
116
117impl<'a, V: SQLParam + 'a> ToSQL<'a, V> for OrderBy {
118 fn to_sql(&self) -> SQL<'a, V> {
119 let sql_str = match self {
120 Self::Asc => "ASC",
121 Self::Desc => "DESC",
122 };
123 SQL::raw(sql_str)
124 }
125}