use super::{SchemaExpressionIndexKeyItemInfo, SchemaInfo};
use crate::{db::IndexState, model::entity::EntityModel};
use std::fmt::Write;
#[must_use]
pub(in crate::db) fn show_indexes_for_model(model: &EntityModel) -> Vec<String> {
show_indexes_for_model_with_runtime_state(model, None)
}
#[must_use]
pub(in crate::db) fn show_indexes_for_model_with_runtime_state(
model: &EntityModel,
runtime_state: Option<IndexState>,
) -> Vec<String> {
let mut indexes = Vec::with_capacity(model.indexes.len().saturating_add(1));
indexes.push(render_index_listing_line(
"PRIMARY KEY",
None,
&[model.primary_key.name],
runtime_state,
Some("generated"),
));
for index in model.indexes {
indexes.push(render_index_listing_line(
if index.is_unique() {
"UNIQUE INDEX"
} else {
"INDEX"
},
Some(index.name()),
index.fields(),
runtime_state,
Some("generated"),
));
}
indexes
}
#[must_use]
pub(in crate::db) fn show_indexes_for_schema_info_with_runtime_state(
schema: &SchemaInfo,
runtime_state: Option<IndexState>,
) -> Vec<String> {
let mut indexes = Vec::with_capacity(
schema
.field_path_indexes()
.len()
.saturating_add(schema.expression_indexes().len())
.saturating_add(1),
);
if let Some(primary_key) = schema.primary_key_name() {
indexes.push(render_index_listing_line(
"PRIMARY KEY",
None,
&[primary_key],
runtime_state,
Some("generated"),
));
}
for index in schema.field_path_indexes() {
let fields: Vec<String> = index
.fields()
.iter()
.map(|field| field.path().join("."))
.collect();
let field_refs: Vec<&str> = fields.iter().map(String::as_str).collect();
indexes.push(render_index_listing_line(
if index.unique() {
"UNIQUE INDEX"
} else {
"INDEX"
},
Some(index.name()),
&field_refs,
runtime_state,
Some(if index.generated() {
"generated"
} else {
"ddl"
}),
));
}
for index in schema.expression_indexes() {
let fields: Vec<String> = index
.key_items()
.iter()
.map(|item| match item {
SchemaExpressionIndexKeyItemInfo::FieldPath(field) => field.path().join("."),
SchemaExpressionIndexKeyItemInfo::Expression(expression) => {
expression.canonical_text().to_string()
}
})
.collect();
let field_refs: Vec<&str> = fields.iter().map(String::as_str).collect();
indexes.push(render_index_listing_line(
if index.unique() {
"UNIQUE INDEX"
} else {
"INDEX"
},
Some(index.name()),
&field_refs,
runtime_state,
Some("generated"),
));
}
indexes
}
fn render_index_listing_line(
kind: &str,
name: Option<&str>,
fields: &[&str],
runtime_state: Option<IndexState>,
origin: Option<&str>,
) -> String {
let mut rendered = String::with_capacity(48 + fields.len().saturating_mul(16));
rendered.push_str(kind);
if let Some(name) = name {
rendered.push(' ');
rendered.push_str(name);
}
rendered.push_str(" (");
for (index, field) in fields.iter().enumerate() {
if index > 0 {
rendered.push_str(", ");
}
rendered.push_str(field);
}
rendered.push(')');
if let Some(state) = runtime_state {
let _ = write!(rendered, " [state={}]", state.as_str());
}
if let Some(origin) = origin {
let _ = write!(rendered, " [origin={origin}]");
}
rendered
}