schema_sql_generator/common/
index_generator.rs1use crate::common::generator_context::GeneratorContext;
2use crate::common::sql_writer::SqlWriter;
3use schema_model::model::key::Key;
4use schema_model::model::table::Table;
5
6const IX_PREFIX: &str = "ix_";
7
8pub trait IndexGenerator {
9 fn output_indexes(&self);
10
11 fn output_indexes_for_table(&self, writer: &mut SqlWriter, table: &Table);
12
13 fn output_index(
14 &self,
15 writer: &mut SqlWriter,
16 statement_separator: &str,
17 table: &Table,
18 key_name: &str,
19 key: &Key,
20 );
21
22 fn index_options(&self, key: &Key) -> Option<String>;
23}
24
25pub struct DefaultIndexGenerator {
26 context: GeneratorContext,
27}
28
29impl DefaultIndexGenerator {
30 pub fn new(context: GeneratorContext) -> Self {
31 Self { context }
32 }
33
34 pub fn context(&self) -> &GeneratorContext {
35 &self.context
36 }
37}
38
39impl IndexGenerator for DefaultIndexGenerator {
40 fn output_indexes(&self) {
41 let database_model = self.context.settings().database_model();
42
43 self.context.with_writer(|writer| {
44 database_model.schemas().iter().for_each(|schema| {
45 schema.tables().iter().for_each(|table| {
46 self.output_indexes_for_table(writer, table);
47 });
48 });
49 });
50 }
51
52 fn output_indexes_for_table(&self, writer: &mut SqlWriter, table: &Table) {
53 if !table.indexes().is_empty() {
54 let max_key_name_length = self
55 .context()
56 .settings()
57 .database_type()
58 .max_key_name_length();
59
60 for (key_index, key) in table
61 .indexes()
62 .iter()
63 .filter(|key| key.is_index())
64 .enumerate()
65 {
66 let mut key_name = format!("{}{}{}", IX_PREFIX, table.name(), key_index + 1);
67
68 if key_name.len() > max_key_name_length {
69 let max_name_len = max_key_name_length.saturating_sub(4); let truncated = table
71 .name()
72 .chars()
73 .take(max_name_len.min(table.name().len()))
74 .collect::<String>();
75 key_name = format!("{}{}{}", IX_PREFIX, truncated, key_index + 1);
76 }
77
78 self.output_index(
79 writer,
80 self.context().settings().statement_separator(),
81 table,
82 key_name.as_str(),
83 key,
84 );
85 }
86
87 writer.newline();
88 }
89 }
90
91 fn output_index(
92 &self,
93 writer: &mut SqlWriter,
94 statement_separator: &str,
95 table: &Table,
96 key_name: &str,
97 key: &Key,
98 ) {
99 let index_options = self.index_options(key);
100 let index_columns = key
101 .columns()
102 .iter()
103 .map(|column| column.name())
104 .collect::<Vec<_>>()
105 .join(", ");
106
107 if index_options.is_some() {
108 writer.println(
109 format!(
110 "create {}index {} on {} ({}) {}{}",
111 if key.is_unique() { "unique " } else { "" },
112 key_name,
113 table.name(),
114 index_columns,
115 index_options.unwrap(),
116 statement_separator
117 )
118 .as_str(),
119 );
120 } else {
121 writer.println(
122 format!(
123 "create {}index {} on {} ({}){}",
124 if key.is_unique() { "unique " } else { "" },
125 key_name,
126 table.name(),
127 index_columns,
128 statement_separator
129 )
130 .as_str(),
131 );
132 }
133 }
134
135 fn index_options(&self, _key: &Key) -> Option<String> {
136 None
137 }
138}