use super::{SchemaExpressionIndexKeyItemInfo, SchemaInfo};
use crate::db::IndexState;
use std::fmt::Write;
#[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 !schema.primary_key_names().is_empty() {
let primary_key_fields = primary_key_fields_from_schema(schema);
indexes.push(render_index_listing_line(
"PRIMARY KEY",
None,
&primary_key_fields,
None,
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,
index.predicate_sql(),
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,
index.predicate_sql(),
runtime_state,
Some(if index.generated() {
"generated"
} else {
"ddl"
}),
));
}
indexes
}
fn primary_key_fields_from_schema(schema: &SchemaInfo) -> Vec<&str> {
schema
.primary_key_names()
.iter()
.map(String::as_str)
.collect()
}
fn render_index_listing_line(
kind: &str,
name: Option<&str>,
fields: &[&str],
predicate_sql: Option<&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(predicate_sql) = predicate_sql {
let _ = write!(rendered, " WHERE {predicate_sql}");
}
if let Some(state) = runtime_state {
let _ = write!(rendered, " [state={}]", state.as_str());
}
if let Some(origin) = origin {
let _ = write!(rendered, " [origin={origin}]");
}
rendered
}